diff options
author | Philip Hazel <ph10@hermes.cam.ac.uk> | 2007-06-26 11:16:54 +0000 |
---|---|---|
committer | Philip Hazel <ph10@hermes.cam.ac.uk> | 2007-06-26 11:16:54 +0000 |
commit | 64f2600a56e0201f23dd3496a499fff6ef22c0c0 (patch) | |
tree | 82b2fb9abb8bbb0d05e63485058224b89b54d95a /src | |
parent | d52120f2b5b5464091a61a47fe881a6e8f6ec09f (diff) |
Installed PCRE 7.2 into Exim.
Diffstat (limited to 'src')
-rwxr-xr-x | src/scripts/MakeLinks | 4 | ||||
-rw-r--r-- | src/src/pcre/ChangeLog | 223 | ||||
-rw-r--r-- | src/src/pcre/LICENCE | 6 | ||||
-rw-r--r-- | src/src/pcre/Makefile | 49 | ||||
-rw-r--r-- | src/src/pcre/config.h | 7 | ||||
-rw-r--r-- | src/src/pcre/dftables.c | 49 | ||||
-rw-r--r-- | src/src/pcre/pcre.h | 108 | ||||
-rw-r--r-- | src/src/pcre/pcre_chartables.c | 196 | ||||
-rw-r--r-- | src/src/pcre/pcre_compile.c | 546 | ||||
-rw-r--r-- | src/src/pcre/pcre_config.c | 6 | ||||
-rw-r--r-- | src/src/pcre/pcre_exec.c | 862 | ||||
-rw-r--r-- | src/src/pcre/pcre_fullinfo.c | 14 | ||||
-rw-r--r-- | src/src/pcre/pcre_get.c | 4 | ||||
-rw-r--r-- | src/src/pcre/pcre_globals.c | 37 | ||||
-rw-r--r-- | src/src/pcre/pcre_internal.h | 380 | ||||
-rw-r--r-- | src/src/pcre/pcre_maketables.c | 4 | ||||
-rw-r--r-- | src/src/pcre/pcre_newline.c | 43 | ||||
-rw-r--r-- | src/src/pcre/pcre_printint.src | 36 | ||||
-rw-r--r-- | src/src/pcre/pcre_study.c | 10 | ||||
-rw-r--r-- | src/src/pcre/pcre_tables.c | 8 | ||||
-rw-r--r-- | src/src/pcre/pcre_try_flipped.c | 4 | ||||
-rw-r--r-- | src/src/pcre/pcre_version.c | 6 | ||||
-rw-r--r-- | src/src/pcre/pcretest.c | 108 | ||||
-rw-r--r-- | src/src/pcre/ucp.h | 2 |
24 files changed, 2121 insertions, 591 deletions
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks index d4561ac39..ce125a8dd 100755 --- a/src/scripts/MakeLinks +++ b/src/scripts/MakeLinks @@ -1,5 +1,5 @@ #!/bin/sh -# $Cambridge: exim/src/scripts/MakeLinks,v 1.10 2007/01/23 15:08:45 ph10 Exp $ +# $Cambridge: exim/src/scripts/MakeLinks,v 1.11 2007/06/26 11:16:54 ph10 Exp $ # Script to build links for all the exim source files from the system- # specific build directory. It should be run from within that directory. @@ -32,10 +32,10 @@ mkdir pcre cd pcre ln -s ../../src/pcre/Makefile Makefile ln -s ../../src/pcre/config.h config.h -ln -s ../../src/pcre/dftables.c dftables.c ln -s ../../src/pcre/pcre_internal.h pcre_internal.h ln -s ../../src/pcre/pcre.h pcre.h ln -s ../../src/pcre/pcre_maketables.c pcre_maketables.c +ln -s ../../src/pcre/pcre_chartables.c pcre_chartables.c ln -s ../../src/pcre/pcre_config.c pcre_config.c ln -s ../../src/pcre/pcre_get.c pcre_get.c ln -s ../../src/pcre/pcre_globals.c pcre_globals.c diff --git a/src/src/pcre/ChangeLog b/src/src/pcre/ChangeLog index 7d32804d0..87c2de74d 100644 --- a/src/src/pcre/ChangeLog +++ b/src/src/pcre/ChangeLog @@ -1,6 +1,229 @@ ChangeLog for PCRE ------------------ +Version 7.2 19-June-07 +--------------------- + + 1. If the fr_FR locale cannot be found for test 3, try the "french" locale, + which is apparently normally available under Windows. + + 2. Re-jig the pcregrep tests with different newline settings in an attempt + to make them independent of the local environment's newline setting. + + 3. Add code to configure.ac to remove -g from the CFLAGS default settings. + + 4. Some of the "internals" tests were previously cut out when the link size + was not 2, because the output contained actual offsets. The recent new + "Z" feature of pcretest means that these can be cut out, making the tests + usable with all link sizes. + + 5. Implemented Stan Switzer's goto replacement for longjmp() when not using + stack recursion. This gives a massive performance boost under BSD, but just + a small improvement under Linux. However, it saves one field in the frame + in all cases. + + 6. Added more features from the forthcoming Perl 5.10: + + (a) (?-n) (where n is a string of digits) is a relative subroutine or + recursion call. It refers to the nth most recently opened parentheses. + + (b) (?+n) is also a relative subroutine call; it refers to the nth next + to be opened parentheses. + + (c) Conditions that refer to capturing parentheses can be specified + relatively, for example, (?(-2)... or (?(+3)... + + (d) \K resets the start of the current match so that everything before + is not part of it. + + (e) \k{name} is synonymous with \k<name> and \k'name' (.NET compatible). + + (f) \g{name} is another synonym - part of Perl 5.10's unification of + reference syntax. + + (g) (?| introduces a group in which the numbering of parentheses in each + alternative starts with the same number. + + (h) \h, \H, \v, and \V match horizontal and vertical whitespace. + + 7. Added two new calls to pcre_fullinfo(): PCRE_INFO_OKPARTIAL and + PCRE_INFO_JCHANGED. + + 8. A pattern such as (.*(.)?)* caused pcre_exec() to fail by either not + terminating or by crashing. Diagnosed by Viktor Griph; it was in the code + for detecting groups that can match an empty string. + + 9. A pattern with a very large number of alternatives (more than several + hundred) was running out of internal workspace during the pre-compile + phase, where pcre_compile() figures out how much memory will be needed. A + bit of new cunning has reduced the workspace needed for groups with + alternatives. The 1000-alternative test pattern now uses 12 bytes of + workspace instead of running out of the 4096 that are available. + +10. Inserted some missing (unsigned int) casts to get rid of compiler warnings. + +11. Applied patch from Google to remove an optimization that didn't quite work. + The report of the bug said: + + pcrecpp::RE("a*").FullMatch("aaa") matches, while + pcrecpp::RE("a*?").FullMatch("aaa") does not, and + pcrecpp::RE("a*?\\z").FullMatch("aaa") does again. + +12. If \p or \P was used in non-UTF-8 mode on a character greater than 127 + it matched the wrong number of bytes. + + +Version 7.1 24-Apr-07 +--------------------- + + 1. Applied Bob Rossi and Daniel G's patches to convert the build system to one + that is more "standard", making use of automake and other Autotools. There + is some re-arrangement of the files and adjustment of comments consequent + on this. + + 2. Part of the patch fixed a problem with the pcregrep tests. The test of -r + for recursive directory scanning broke on some systems because the files + are not scanned in any specific order and on different systems the order + was different. A call to "sort" has been inserted into RunGrepTest for the + approprate test as a short-term fix. In the longer term there may be an + alternative. + + 3. I had an email from Eric Raymond about problems translating some of PCRE's + man pages to HTML (despite the fact that I distribute HTML pages, some + people do their own conversions for various reasons). The problems + concerned the use of low-level troff macros .br and .in. I have therefore + removed all such uses from the man pages (some were redundant, some could + be replaced by .nf/.fi pairs). The 132html script that I use to generate + HTML has been updated to handle .nf/.fi and to complain if it encounters + .br or .in. + + 4. Updated comments in configure.ac that get placed in config.h.in and also + arranged for config.h to be included in the distribution, with the name + config.h.generic, for the benefit of those who have to compile without + Autotools (compare pcre.h, which is now distributed as pcre.h.generic). + + 5. Updated the support (such as it is) for Virtual Pascal, thanks to Stefan + Weber: (1) pcre_internal.h was missing some function renames; (2) updated + makevp.bat for the current PCRE, using the additional files + makevp_c.txt, makevp_l.txt, and pcregexp.pas. + + 6. A Windows user reported a minor discrepancy with test 2, which turned out + to be caused by a trailing space on an input line that had got lost in his + copy. The trailing space was an accident, so I've just removed it. + + 7. Add -Wl,-R... flags in pcre-config.in for *BSD* systems, as I'm told + that is needed. + + 8. Mark ucp_table (in ucptable.h) and ucp_gentype (in pcre_ucp_searchfuncs.c) + as "const" (a) because they are and (b) because it helps the PHP + maintainers who have recently made a script to detect big data structures + in the php code that should be moved to the .rodata section. I remembered + to update Builducptable as well, so it won't revert if ucptable.h is ever + re-created. + + 9. Added some extra #ifdef SUPPORT_UTF8 conditionals into pcretest.c, + pcre_printint.src, pcre_compile.c, pcre_study.c, and pcre_tables.c, in + order to be able to cut out the UTF-8 tables in the latter when UTF-8 + support is not required. This saves 1.5-2K of code, which is important in + some applications. + + Later: more #ifdefs are needed in pcre_ord2utf8.c and pcre_valid_utf8.c + so as not to refer to the tables, even though these functions will never be + called when UTF-8 support is disabled. Otherwise there are problems with a + shared library. + +10. Fixed two bugs in the emulated memmove() function in pcre_internal.h: + + (a) It was defining its arguments as char * instead of void *. + + (b) It was assuming that all moves were upwards in memory; this was true + a long time ago when I wrote it, but is no longer the case. + + The emulated memove() is provided for those environments that have neither + memmove() nor bcopy(). I didn't think anyone used it these days, but that + is clearly not the case, as these two bugs were recently reported. + +11. The script PrepareRelease is now distributed: it calls 132html, CleanTxt, + and Detrail to create the HTML documentation, the .txt form of the man + pages, and it removes trailing spaces from listed files. It also creates + pcre.h.generic and config.h.generic from pcre.h and config.h. In the latter + case, it wraps all the #defines with #ifndefs. This script should be run + before "make dist". + +12. Fixed two fairly obscure bugs concerned with quantified caseless matching + with Unicode property support. + + (a) For a maximizing quantifier, if the two different cases of the + character were of different lengths in their UTF-8 codings (there are + some cases like this - I found 11), and the matching function had to + back up over a mixture of the two cases, it incorrectly assumed they + were both the same length. + + (b) When PCRE was configured to use the heap rather than the stack for + recursion during matching, it was not correctly preserving the data for + the other case of a UTF-8 character when checking ahead for a match + while processing a minimizing repeat. If the check also involved + matching a wide character, but failed, corruption could cause an + erroneous result when trying to check for a repeat of the original + character. + +13. Some tidying changes to the testing mechanism: + + (a) The RunTest script now detects the internal link size and whether there + is UTF-8 and UCP support by running ./pcretest -C instead of relying on + values substituted by "configure". (The RunGrepTest script already did + this for UTF-8.) The configure.ac script no longer substitutes the + relevant variables. + + (b) The debugging options /B and /D in pcretest show the compiled bytecode + with length and offset values. This means that the output is different + for different internal link sizes. Test 2 is skipped for link sizes + other than 2 because of this, bypassing the problem. Unfortunately, + there was also a test in test 3 (the locale tests) that used /B and + failed for link sizes other than 2. Rather than cut the whole test out, + I have added a new /Z option to pcretest that replaces the length and + offset values with spaces. This is now used to make test 3 independent + of link size. (Test 2 will be tidied up later.) + +14. If erroroffset was passed as NULL to pcre_compile, it provoked a + segmentation fault instead of returning the appropriate error message. + +15. In multiline mode when the newline sequence was set to "any", the pattern + ^$ would give a match between the \r and \n of a subject such as "A\r\nB". + This doesn't seem right; it now treats the CRLF combination as the line + ending, and so does not match in that case. It's only a pattern such as ^$ + that would hit this one: something like ^ABC$ would have failed after \r + and then tried again after \r\n. + +16. Changed the comparison command for RunGrepTest from "diff -u" to "diff -ub" + in an attempt to make files that differ only in their line terminators + compare equal. This works on Linux. + +17. Under certain error circumstances pcregrep might try to free random memory + as it exited. This is now fixed, thanks to valgrind. + +19. In pcretest, if the pattern /(?m)^$/g<any> was matched against the string + "abc\r\n\r\n", it found an unwanted second match after the second \r. This + was because its rules for how to advance for /g after matching an empty + string at the end of a line did not allow for this case. They now check for + it specially. + +20. pcretest is supposed to handle patterns and data of any length, by + extending its buffers when necessary. It was getting this wrong when the + buffer for a data line had to be extended. + +21. Added PCRE_NEWLINE_ANYCRLF which is like ANY, but matches only CR, LF, or + CRLF as a newline sequence. + +22. Code for handling Unicode properties in pcre_dfa_exec() wasn't being cut + out by #ifdef SUPPORT_UCP. This did no harm, as it could never be used, but + I have nevertheless tidied it up. + +23. Added some casts to kill warnings from HP-UX ia64 compiler. + +24. Added a man page for pcre-config. + + Version 7.0 19-Dec-06 --------------------- diff --git a/src/src/pcre/LICENCE b/src/src/pcre/LICENCE index 58241b2bd..4baa7d83a 100644 --- a/src/src/pcre/LICENCE +++ b/src/src/pcre/LICENCE @@ -20,9 +20,9 @@ Email local part: ph10 Email domain: cam.ac.uk University of Cambridge Computing Service, -Cambridge, England. Phone: +44 1223 334714. +Cambridge, England. -Copyright (c) 1997-2006 University of Cambridge +Copyright (c) 1997-2007 University of Cambridge All rights reserved. @@ -31,7 +31,7 @@ THE C++ WRAPPER FUNCTIONS Contributed by: Google Inc. -Copyright (c) 2006, Google Inc. +Copyright (c) 2007, Google Inc. All rights reserved. diff --git a/src/src/pcre/Makefile b/src/src/pcre/Makefile index 7079d75f5..400b3c3a5 100644 --- a/src/src/pcre/Makefile +++ b/src/src/pcre/Makefile @@ -1,4 +1,4 @@ -# $Cambridge: exim/src/src/pcre/Makefile,v 1.7 2007/01/23 15:08:45 ph10 Exp $ +# $Cambridge: exim/src/src/pcre/Makefile,v 1.8 2007/06/26 11:16:54 ph10 Exp $ # Makefile for PCRE (Perl-Compatible Regular Expression) library for use by # Exim. This is a tailored Makefile, not the normal one that comes with the @@ -8,12 +8,12 @@ AR = ar cq CC = gcc -O2 -Wall -CFLAGS = +CFLAGS = -I. RANLIB = @true ############################################################################## -OBJ = pcre_maketables.o chartables.o pcre_fullinfo.o pcre_get.o \ +OBJ = pcre_maketables.o pcre_chartables.o pcre_fullinfo.o pcre_get.o \ pcre_globals.o pcre_compile.o pcre_config.o pcre_exec.o pcre_newline.o \ pcre_study.o pcre_tables.o pcre_try_flipped.o pcre_version.o @@ -21,7 +21,7 @@ all: libpcre.a ../pcretest ../pcretest: libpcre.a pcretest.o @echo "$(CC) -o ../pcretest pcretest.o libpcre.a" - $(FE)$(CC) $(CFLAGS) -o ../pcretest pcretest.o libpcre.a + $(FE)$(CC) $(CFLAGS) -I. -o ../pcretest pcretest.o libpcre.a libpcre.a: $(OBJ) -rm -f libpcre.a @@ -29,69 +29,60 @@ libpcre.a: $(OBJ) $(FE)$(AR) libpcre.a $(OBJ) $(RANLIB) libpcre.a -chartables.o: chartables.c pcre_compile.c config.h pcre.h pcre_internal.h Makefile - @echo "$(CC) chartables.c" - $(FE)$(CC) -c $(CFLAGS) chartables.c +pcre_chartables.o: pcre_chartables.c pcre_compile.c config.h pcre.h pcre_internal.h Makefile + @echo "$(CC) pcre_chartables.c" + $(FE)$(CC) -c $(CFLAGS) -I. pcre_chartables.c pcre_compile.o: pcre_compile.c config.h pcre.h pcre_internal.h Makefile @echo "$(CC) pcre_compile.c" - $(FE)$(CC) -c $(CFLAGS) pcre_compile.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_compile.c pcre_config.o: pcre_config.c config.h pcre.h pcre_internal.h Makefile @echo "$(CC) pcre_config.c" - $(FE)$(CC) -c $(CFLAGS) pcre_config.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_config.c -pcre_exec.o: chartables.c pcre_exec.c config.h pcre.h pcre_internal.h Makefile +pcre_exec.o: pcre_chartables.c pcre_exec.c config.h pcre.h pcre_internal.h Makefile @echo "$(CC) pcre_exec.c" - $(FE)$(CC) -c $(CFLAGS) pcre_exec.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_exec.c pcre_maketables.o: pcre_maketables.c config.h pcre.h pcre_internal.h Makefile - @echo "$(CC) pcre_maketables.c" + @echo "$(CC) pcre_maketables.c" $(FE)$(CC) -c $(CFLAGS) pcre_maketables.c pcre_fullinfo.o: pcre_fullinfo.c pcre.h config.h pcre_internal.h Makefile @echo "$(CC) pcre_fullinfo.c" - $(FE)$(CC) -c $(CFLAGS) pcre_fullinfo.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_fullinfo.c pcre_get.o: pcre_get.c pcre.h config.h pcre_internal.h Makefile @echo "$(CC) pcre_get.c" - $(FE)$(CC) -c $(CFLAGS) pcre_get.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_get.c pcre_globals.o: pcre_globals.c pcre.h config.h pcre_internal.h Makefile @echo "$(CC) pcre_globals.c" - $(FE)$(CC) -c $(CFLAGS) pcre_globals.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_globals.c pcre_newline.o: pcre_newline.c pcre.h config.h pcre_internal.h Makefile @echo "$(CC) pcre_newline.c" - $(FE)$(CC) -c $(CFLAGS) pcre_newline.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_newline.c pcre_study.o: pcre_study.c pcre.h config.h pcre_internal.h Makefile @echo "$(CC) pcre_study.c" - $(FE)$(CC) -c $(CFLAGS) pcre_study.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_study.c pcre_tables.o: pcre_tables.c pcre.h config.h pcre_internal.h Makefile @echo "$(CC) pcre_tables.c" - $(FE)$(CC) -c $(CFLAGS) pcre_tables.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_tables.c pcre_try_flipped.o: pcre_try_flipped.c pcre.h config.h pcre_internal.h Makefile @echo "$(CC) pcre_try_flipped.c" - $(FE)$(CC) -c $(CFLAGS) pcre_try_flipped.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_try_flipped.c pcre_version.o: pcre_version.c config.h pcre.h pcre_internal.h Makefile @echo "$(CC) pcre_version.c" - $(FE)$(CC) -c $(CFLAGS) pcre_version.c + $(FE)$(CC) -c $(CFLAGS) -I. pcre_version.c pcretest.o: pcretest.c config.h pcre.h pcre_internal.h Makefile @echo "$(CC) pcretest.c" $(FE)$(CC) -c -DNOPOSIX -DNODFA -DNOUTF8 -DNOINFOCHECK $(CFLAGS) -I. pcretest.c -# An auxiliary program makes the default character table source - -chartables.c: dftables - ./dftables chartables.c - -dftables: dftables.c pcre_maketables.c config.h pcre.h pcre_internal.h Makefile - @echo "$(CC) dftables.c" - $(FE)$(CC) -o dftables $(CFLAGS) dftables.c - # End diff --git a/src/src/pcre/config.h b/src/src/pcre/config.h index 715471ee1..51bd998bb 100644 --- a/src/src/pcre/config.h +++ b/src/src/pcre/config.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/config.h,v 1.2 2006/11/07 16:50:36 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/config.h,v 1.3 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * config.h for PCRE for Exim * @@ -36,9 +36,8 @@ PCRE, can be adjusted by "configure". */ #define MAX_DUPLENGTH 30000 /* There is some stuff in the PCRE sources for compilation on non-Unix systems -and non-ASCII systems. For Exim's purposes, just flatten it all. */ +and non-ASCII systems. For Exim's purposes, just flatten it. */ -#define EBCDIC 0 -#define EXPORT +#undef EBCDIC /* End */ diff --git a/src/src/pcre/dftables.c b/src/src/pcre/dftables.c index bc01eb7f2..e1a2d6f83 100644 --- a/src/src/pcre/dftables.c +++ b/src/src/pcre/dftables.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/dftables.c,v 1.5 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/dftables.c,v 1.6 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -40,14 +40,15 @@ POSSIBILITY OF SUCH DAMAGE. */ -/* This is a freestanding support program to generate a file containing default -character tables for PCRE. The tables are built according to the default C +/* 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. */ #include <ctype.h> #include <stdio.h> #include <string.h> +#include <locale.h> #include "pcre_internal.h" @@ -57,38 +58,48 @@ make use of its code from here in order to be consistent. */ int main(int argc, char **argv) { -int i; FILE *f; -const unsigned char *tables = pcre_maketables(); -const unsigned char *base_of_tables = tables; +int i = 1; +const unsigned char *tables; +const unsigned char *base_of_tables; -if (argc != 2) +/* 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; } -f = fopen(argv[1], "wb"); +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 two fprintf() calls here, because gcc in pedantic mode complains -about the very long string otherwise. */ +/* 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 is automatically written by the dftables auxiliary \n" - "program. If you edit it by hand, you might like to edit the Makefile to \n" - "prevent its ever being regenerated.\n\n"); -fprintf(f, - "This file contains the default tables for characters with codes less than\n" - "128 (ASCII characters). These tables are used when no external tables are\n" - "passed to PCRE.\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 #include is present because without it gcc 4.x may remove\n" "the array definition from the final binary if PCRE is built into a static\n" @@ -173,7 +184,7 @@ 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 chartables.c */\n"); +fprintf(f, " */\n\n/* End of pcre_chartables.c */\n"); fclose(f); free((void *)base_of_tables); diff --git a/src/src/pcre/pcre.h b/src/src/pcre/pcre.h index 6c3f2a50b..c46b8acd7 100644 --- a/src/src/pcre/pcre.h +++ b/src/src/pcre/pcre.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre.h,v 1.5 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre.h,v 1.6 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -7,7 +7,7 @@ /* This is the public header file for the PCRE library, to be #included by applications that call the PCRE functions. - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -43,44 +43,31 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ -/* NOTES FOR FUTURE MAINTAINERS: Do not use numbers with leading zeros, because -they may be treated as octal constants. The PCRE_PRERELEASE feature is for -identifying release candidates. It might be defined as -RC2, for example. In -real releases, it should be defined empty. Do not change the alignment of these -statments. The code in ./configure greps out the version numbers by using "cut" -to get values from column 29 onwards. These are substituted into pcre-config -and libpcre.pc. The values are not put into configure.ac and substituted here -(which would simplify this issue) because that makes life harder for those who -cannot run ./configure. As it now stands, this file need not be edited in that -circumstance. */ - #define PCRE_MAJOR 7 -#define PCRE_MINOR 0 -#define PCRE_PRERELEASE -#define PCRE_DATE 18-Dec-2006 +#define PCRE_MINOR 2 +#define PCRE_PRERELEASE +#define PCRE_DATE 2007-06-19 -/* Win32 uses DLL by default; it needs special stuff for exported functions -when building PCRE. */ +/* 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 an existing definition of PCRE_EXP_DECL. */ -#ifdef _WIN32 -# ifdef PCRE_DEFINITION -# ifdef DLL_EXPORT -# define PCRE_DATA_SCOPE __declspec(dllexport) -# endif -# else +#ifndef PCRE_EXP_DECL +# ifdef _WIN32 # ifndef PCRE_STATIC -# define PCRE_DATA_SCOPE extern __declspec(dllimport) +# define PCRE_EXP_DECL extern __declspec(dllimport) # endif # endif #endif -/* Otherwise, we use the standard "extern". */ +/* By default, we use the standard "extern" declarations. */ -#ifndef PCRE_DATA_SCOPE +#ifndef PCRE_EXP_DECL # ifdef __cplusplus -# define PCRE_DATA_SCOPE extern "C" +# define PCRE_EXP_DECL extern "C" # else -# define PCRE_DATA_SCOPE extern +# define PCRE_EXP_DECL extern # endif #endif @@ -121,6 +108,7 @@ extern "C" { #define PCRE_NEWLINE_LF 0x00200000 #define PCRE_NEWLINE_CRLF 0x00300000 #define PCRE_NEWLINE_ANY 0x00400000 +#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* Exec-time and get/set-time error codes */ @@ -164,6 +152,8 @@ extern "C" { #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 /* Request types for pcre_config(). Do not re-arrange, in order to remain compatible. */ @@ -242,52 +232,52 @@ that is triggered by the (?) regex item. For Virtual Pascal, these definitions have to take another form. */ #ifndef VPCOMPAT -PCRE_DATA_SCOPE void *(*pcre_malloc)(size_t); -PCRE_DATA_SCOPE void (*pcre_free)(void *); -PCRE_DATA_SCOPE void *(*pcre_stack_malloc)(size_t); -PCRE_DATA_SCOPE void (*pcre_stack_free)(void *); -PCRE_DATA_SCOPE int (*pcre_callout)(pcre_callout_block *); +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 *); #else /* VPCOMPAT */ -PCRE_DATA_SCOPE void *pcre_malloc(size_t); -PCRE_DATA_SCOPE void pcre_free(void *); -PCRE_DATA_SCOPE void *pcre_stack_malloc(size_t); -PCRE_DATA_SCOPE void pcre_stack_free(void *); -PCRE_DATA_SCOPE int pcre_callout(pcre_callout_block *); +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 *); #endif /* VPCOMPAT */ /* Exported PCRE functions */ -PCRE_DATA_SCOPE pcre *pcre_compile(const char *, int, const char **, int *, +PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *, const unsigned char *); -PCRE_DATA_SCOPE pcre *pcre_compile2(const char *, int, int *, const char **, +PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **, int *, const unsigned char *); -PCRE_DATA_SCOPE int pcre_config(int, void *); -PCRE_DATA_SCOPE int pcre_copy_named_substring(const pcre *, const char *, +PCRE_EXP_DECL int pcre_config(int, void *); +PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *, int *, int, const char *, char *, int); -PCRE_DATA_SCOPE int pcre_copy_substring(const char *, int *, int, int, char *, +PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, char *, int); -PCRE_DATA_SCOPE int pcre_dfa_exec(const pcre *, const pcre_extra *, +PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *, const char *, int, int, int, int *, int , int *, int); -PCRE_DATA_SCOPE int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, +PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int); -PCRE_DATA_SCOPE void pcre_free_substring(const char *); -PCRE_DATA_SCOPE void pcre_free_substring_list(const char **); -PCRE_DATA_SCOPE int pcre_fullinfo(const pcre *, const pcre_extra *, int, +PCRE_EXP_DECL void pcre_free_substring(const char *); +PCRE_EXP_DECL void pcre_free_substring_list(const char **); +PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int, void *); -PCRE_DATA_SCOPE int pcre_get_named_substring(const pcre *, const char *, +PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *, int *, int, const char *, const char **); -PCRE_DATA_SCOPE int pcre_get_stringnumber(const pcre *, const char *); -PCRE_DATA_SCOPE int pcre_get_stringtable_entries(const pcre *, const char *, +PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *); +PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, char **, char **); -PCRE_DATA_SCOPE int pcre_get_substring(const char *, int *, int, int, +PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, const char **); -PCRE_DATA_SCOPE int pcre_get_substring_list(const char *, int *, int, +PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int, const char ***); -PCRE_DATA_SCOPE int pcre_info(const pcre *, int *, int *); -PCRE_DATA_SCOPE const unsigned char *pcre_maketables(void); -PCRE_DATA_SCOPE int pcre_refcount(pcre *, int); -PCRE_DATA_SCOPE pcre_extra *pcre_study(const pcre *, int, const char **); -PCRE_DATA_SCOPE const char *pcre_version(void); +PCRE_EXP_DECL int pcre_info(const pcre *, int *, int *); +PCRE_EXP_DECL const unsigned char *pcre_maketables(void); +PCRE_EXP_DECL int pcre_refcount(pcre *, int); +PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **); +PCRE_EXP_DECL const char *pcre_version(void); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/src/pcre/pcre_chartables.c b/src/src/pcre/pcre_chartables.c new file mode 100644 index 000000000..acc852821 --- /dev/null +++ b/src/src/pcre/pcre_chartables.c @@ -0,0 +1,196 @@ +/* $Cambridge: exim/src/src/pcre/pcre_chartables.c,v 1.1 2007/06/26 11:16:54 ph10 Exp $ */ + +/************************************************* +* 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 #include is present because without it 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. */ + +#include "pcre_internal.h" + +const unsigned char _pcre_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 */ diff --git a/src/src/pcre/pcre_compile.c b/src/src/pcre/pcre_compile.c index f7a3ebbd2..4d179e3fe 100644 --- a/src/src/pcre/pcre_compile.c +++ b/src/src/pcre/pcre_compile.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_compile.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_compile.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -60,6 +60,11 @@ used by pcretest. DEBUG is not defined when building a production library. */ #endif +/* Macro for setting individual bits in class bitmaps. */ + +#define SETBIT(a,b) a[b/8] |= (1 << (b%8)) + + /************************************************* * Code parameters and static tables * *************************************************/ @@ -84,21 +89,21 @@ 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. */ -#if !EBCDIC /* This is the "normal" table for ASCII systems */ +#ifndef EBCDIC /* This is the "normal" table for ASCII systems */ static const short int escapes[] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */ 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */ '@', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G, /* @ - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ --ESC_P, -ESC_Q, -ESC_R, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */ +-ESC_H, 0, 0, -ESC_K, 0, 0, 0, 0, /* H - O */ +-ESC_P, -ESC_Q, -ESC_R, -ESC_S, 0, 0, -ESC_V, -ESC_W, /* P - W */ -ESC_X, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */ '`', 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* ` - g */ - 0, 0, 0, -ESC_k, 0, 0, ESC_n, 0, /* h - o */ --ESC_p, 0, ESC_r, -ESC_s, ESC_tee, 0, 0, -ESC_w, /* p - w */ +-ESC_h, 0, 0, -ESC_k, 0, 0, ESC_n, 0, /* h - o */ +-ESC_p, 0, ESC_r, -ESC_s, ESC_tee, 0, -ESC_v, -ESC_w, /* p - w */ 0, 0, -ESC_z /* x - z */ }; -#else /* This is the "abnormal" table for EBCDIC systems */ +#else /* This is the "abnormal" table for EBCDIC systems */ static const short int escapes[] = { /* 48 */ 0, 0, 0, '.', '<', '(', '+', '|', /* 50 */ '&', 0, 0, 0, 0, 0, 0, 0, @@ -108,18 +113,18 @@ static const short int escapes[] = { /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', /* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, -/* 88 */ 0, 0, 0, '{', 0, 0, 0, 0, +/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0, /* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p, /* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, -/* A0 */ 0, '~', -ESC_s, ESC_tee, 0, 0, -ESC_w, 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 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* C8 */-ESC_H, 0, 0, 0, 0, 0, 0, 0, /* D0 */ '}', 0, 0, 0, 0, 0, 0, -ESC_P, /* D8 */-ESC_Q,-ESC_R, 0, 0, 0, 0, 0, 0, -/* E0 */ '\\', 0, -ESC_S, 0, 0, 0, -ESC_W, -ESC_X, +/* 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 @@ -210,7 +215,7 @@ static const char *error_texts[] = { "malformed number or name after (?(", "conditional group contains more than two branches", "assertion expected after (?(", - "(?R or (?digits must be followed by )", + "(?R or (?[+-]digits must be followed by )", /* 30 */ "unknown POSIX class name", "POSIX collating elements are not supported", @@ -244,7 +249,8 @@ static const char *error_texts[] = { /* 55 */ "repeating a DEFINE group is not allowed", "inconsistent NEWLINE options", - "\\g is not followed by an (optionally braced) non-zero number" + "\\g is not followed by a braced name or an optionally braced non-zero number", + "(?+ or (?- or (?(+ or (?(- must be followed by a non-zero number" }; @@ -264,7 +270,7 @@ For convenience, we use the same bit definitions as in chartables: Then we can use ctype_digit and ctype_xdigit in the code. */ -#if !EBCDIC /* This is the "normal" case, for ASCII systems */ +#ifndef EBCDIC /* This is the "normal" case, for ASCII systems */ static const unsigned char digitab[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ @@ -300,7 +306,7 @@ static const unsigned char digitab[] = 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 */ +#else /* This is the "abnormal" case, for EBCDIC systems */ static const unsigned char digitab[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */ @@ -314,7 +320,7 @@ static const unsigned char digitab[] = 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- ¬ */ + 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 */ @@ -348,7 +354,7 @@ static const unsigned char ebcdic_chartab[] = { /* chartable partial dup */ 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- ¬ */ + 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 */ @@ -375,8 +381,8 @@ static const unsigned char ebcdic_chartab[] = { /* chartable partial dup */ /* Definition to allow mutual recursion */ static BOOL - compile_regex(int, int, uschar **, const uschar **, int *, BOOL, int, int *, - int *, branch_chain *, compile_data *, int *); + compile_regex(int, int, uschar **, const uschar **, int *, BOOL, BOOL, int, + int *, int *, branch_chain *, compile_data *, int *); @@ -423,11 +429,11 @@ if (c == 0) *errorcodeptr = ERR1; a table. A non-zero result is something that can be returned immediately. Otherwise further processing may be required. */ -#if !EBCDIC /* ASCII coding */ +#ifndef EBCDIC /* ASCII coding */ else if (c < '0' || c > 'z') {} /* Not alphameric */ else if ((i = escapes[c - '0']) != 0) c = i; -#else /* EBCDIC coding */ +#else /* EBCDIC coding */ else if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {} /* Not alphameric */ else if ((i = escapes[c - 0x48]) != 0) c = i; #endif @@ -454,11 +460,22 @@ else /* \g must be followed by 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. */ + This is a Perl 5.10 feature. 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. */ case 'g': if (ptr[1] == '{') { + const uschar *p; + for (p = ptr+2; *p != 0 && *p != '}'; p++) + if (*p != '-' && (digitab[*p] & ctype_digit) == 0) break; + if (*p != 0 && *p != '}') + { + c = -ESC_k; + break; + } braced = TRUE; ptr++; } @@ -564,10 +581,10 @@ else if (c == 0 && cc == '0') continue; /* Leading zeroes */ count++; -#if !EBCDIC /* ASCII coding */ +#ifndef EBCDIC /* ASCII coding */ if (cc >= 'a') cc -= 32; /* Convert to upper case */ c = (c << 4) + cc - ((cc < 'A')? '0' : ('A' - 10)); -#else /* EBCDIC coding */ +#else /* EBCDIC coding */ if (cc >= 'a' && cc <= 'z') cc += 64; /* Convert to upper case */ c = (c << 4) + cc - ((cc >= '0')? '0' : ('A' - 10)); #endif @@ -591,10 +608,10 @@ else { int cc; /* Some compilers don't like ++ */ cc = *(++ptr); /* in initializers */ -#if !EBCDIC /* ASCII coding */ +#ifndef EBCDIC /* ASCII coding */ if (cc >= 'a') cc -= 32; /* Convert to upper case */ c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); -#else /* EBCDIC coding */ +#else /* EBCDIC coding */ if (cc <= 'z') cc += 64; /* Convert to upper case */ c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10)); #endif @@ -613,10 +630,10 @@ else return 0; } -#if !EBCDIC /* ASCII coding */ +#ifndef EBCDIC /* ASCII coding */ if (c >= 'a' && c <= 'z') c -= 32; c ^= 0x40; -#else /* EBCDIC coding */ +#else /* EBCDIC coding */ if (c >= 'a' && c <= 'z') c += 64; c ^= 0xC0; #endif @@ -1248,6 +1265,7 @@ for (;;) else { code += _pcre_OP_lengths[c]; +#ifdef SUPPORT_UTF8 if (utf8) switch(c) { case OP_CHAR: @@ -1268,6 +1286,7 @@ for (;;) if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f]; break; } +#endif } } } @@ -1311,6 +1330,7 @@ for (;;) else { code += _pcre_OP_lengths[c]; +#ifdef SUPPORT_UTF8 if (utf8) switch(c) { case OP_CHAR: @@ -1331,6 +1351,7 @@ for (;;) if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f]; break; } +#endif } } } @@ -1368,6 +1389,18 @@ for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE c = *code; + /* Groups with zero repeats can of course be empty; skip them. */ + + if (c == OP_BRAZERO || c == OP_BRAMINZERO) + { + code += _pcre_OP_lengths[c]; + do code += GET(code, 1); while (*code == OP_ALT); + c = *code; + continue; + } + + /* For other groups, scan the branches. */ + if (c == OP_BRA || c == OP_CBRA || c == OP_ONCE) { BOOL empty_branch; @@ -1384,12 +1417,7 @@ for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE } while (*code == OP_ALT); if (!empty_branch) return FALSE; /* All branches are non-empty */ - - /* Move past the KET and fudge things so that the increment in the "for" - above has no effect. */ - - c = OP_END; - code += 1 + LINK_SIZE - _pcre_OP_lengths[c]; + c = *code; continue; } @@ -1923,6 +1951,50 @@ if (next >= 0) switch(op_code) case OP_NOT_WORDCHAR: return next <= 127 && (cd->ctypes[next] & ctype_word) != 0; + case OP_HSPACE: + case OP_NOT_HSPACE: + switch(next) + { + case 0x09: + case 0x20: + case 0xa0: + case 0x1680: + case 0x180e: + case 0x2000: + case 0x2001: + case 0x2002: + case 0x2003: + case 0x2004: + case 0x2005: + case 0x2006: + case 0x2007: + case 0x2008: + case 0x2009: + case 0x200A: + case 0x202f: + case 0x205f: + case 0x3000: + return op_code != OP_HSPACE; + default: + return op_code == OP_HSPACE; + } + + case OP_VSPACE: + case OP_NOT_VSPACE: + switch(next) + { + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x85: + case 0x2028: + case 0x2029: + return op_code != OP_VSPACE; + default: + return op_code == OP_VSPACE; + } + default: return FALSE; } @@ -1957,12 +2029,57 @@ switch(op_code) case ESC_W: return item <= 127 && (cd->ctypes[item] & ctype_word) != 0; + case ESC_h: + case ESC_H: + switch(item) + { + case 0x09: + case 0x20: + case 0xa0: + case 0x1680: + case 0x180e: + case 0x2000: + case 0x2001: + case 0x2002: + case 0x2003: + case 0x2004: + case 0x2005: + case 0x2006: + case 0x2007: + case 0x2008: + case 0x2009: + case 0x200A: + case 0x202f: + case 0x205f: + case 0x3000: + return -next != ESC_h; + default: + return -next == ESC_h; + } + + case ESC_v: + case ESC_V: + switch(item) + { + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x85: + case 0x2028: + case 0x2029: + return -next != ESC_v; + default: + return -next == ESC_v; + } + default: return FALSE; } case OP_DIGIT: - return next == -ESC_D || next == -ESC_s || next == -ESC_W; + return next == -ESC_D || next == -ESC_s || next == -ESC_W || + next == -ESC_h || next == -ESC_v; case OP_NOT_DIGIT: return next == -ESC_d; @@ -1971,10 +2088,23 @@ switch(op_code) return next == -ESC_S || next == -ESC_d || next == -ESC_w; case OP_NOT_WHITESPACE: - return next == -ESC_s; + return next == -ESC_s || next == -ESC_h || next == -ESC_v; + + case OP_HSPACE: + return next == -ESC_S || next == -ESC_H || next == -ESC_d || next == -ESC_w; + + case OP_NOT_HSPACE: + return next == -ESC_h; + + /* Can't have \S in here because VT matches \S (Perl anomaly) */ + case OP_VSPACE: + return next == -ESC_V || next == -ESC_d || next == -ESC_w; + + case OP_NOT_VSPACE: + return next == -ESC_v; case OP_WORDCHAR: - return next == -ESC_W || next == -ESC_s; + return next == -ESC_W || next == -ESC_s || next == -ESC_h || next == -ESC_v; case OP_NOT_WORDCHAR: return next == -ESC_w || next == -ESC_d; @@ -2089,10 +2219,12 @@ for (;; ptr++) BOOL possessive_quantifier; BOOL is_quantifier; BOOL is_recurse; + BOOL reset_bracount; int class_charcount; int class_lastchar; int newoptions; int recno; + int refsign; int skipbytes; int subreqbyte; int subfirstbyte; @@ -2517,6 +2649,133 @@ for (;; ptr++) else if (c == -ESC_d || c == -ESC_D || c == -ESC_w || c == -ESC_W || c == -ESC_s || c == -ESC_S) continue; + /* We need to deal with \H, \h, \V, and \v in both phases because + they use extra memory. */ + + if (-c == ESC_h) + { + SETBIT(classbits, 0x09); /* VT */ + SETBIT(classbits, 0x20); /* SPACE */ + SETBIT(classbits, 0xa0); /* NSBP */ +#ifdef SUPPORT_UTF8 + if (utf8) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x1680, class_utf8data); + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x180e, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2000, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x200A, class_utf8data); + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x202f, class_utf8data); + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x205f, class_utf8data); + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x3000, class_utf8data); + } +#endif + continue; + } + + if (-c == ESC_H) + { + for (c = 0; c < 32; c++) + { + int x = 0xff; + switch (c) + { + case 0x09/8: x ^= 1 << (0x09%8); break; + case 0x20/8: x ^= 1 << (0x20%8); break; + case 0xa0/8: x ^= 1 << (0xa0%8); break; + default: break; + } + classbits[c] |= x; + } + +#ifdef SUPPORT_UTF8 + if (utf8) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x0100, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x167f, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x1681, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x180d, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x180f, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x1fff, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x200B, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x202e, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2030, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x205e, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2060, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x2fff, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x3001, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x7fffffff, class_utf8data); + } +#endif + continue; + } + + if (-c == ESC_v) + { + SETBIT(classbits, 0x0a); /* LF */ + SETBIT(classbits, 0x0b); /* VT */ + SETBIT(classbits, 0x0c); /* FF */ + SETBIT(classbits, 0x0d); /* CR */ + SETBIT(classbits, 0x85); /* NEL */ +#ifdef SUPPORT_UTF8 + if (utf8) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2028, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x2029, class_utf8data); + } +#endif + continue; + } + + if (-c == ESC_V) + { + for (c = 0; c < 32; c++) + { + int x = 0xff; + switch (c) + { + case 0x0a/8: x ^= 1 << (0x0a%8); + x ^= 1 << (0x0b%8); + x ^= 1 << (0x0c%8); + x ^= 1 << (0x0d%8); + break; + case 0x85/8: x ^= 1 << (0x85%8); break; + default: break; + } + classbits[c] |= x; + } + +#ifdef SUPPORT_UTF8 + if (utf8) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x0100, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x2027, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2029, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x7fffffff, class_utf8data); + } +#endif + continue; + } + /* We need to deal with \P and \p in both phases. */ #ifdef SUPPORT_UCP @@ -2657,14 +2916,18 @@ for (;; ptr++) unsigned int origd = d; while (get_othercase_range(&cc, origd, &occ, &ocd)) { - if (occ >= c && ocd <= d) continue; /* Skip embedded ranges */ + if (occ >= (unsigned int)c && + ocd <= (unsigned int)d) + continue; /* Skip embedded ranges */ - if (occ < c && ocd >= c - 1) /* Extend the basic range */ + if (occ < (unsigned int)c && + ocd >= (unsigned int)c - 1) /* Extend the basic range */ { /* if there is overlap, */ c = occ; /* noting that if occ < c */ continue; /* we can't have ocd > d */ } /* because a subrange is */ - if (ocd > d && occ <= d + 1) /* always shorter than */ + if (ocd > (unsigned int)d && + occ <= (unsigned int)d + 1) /* always shorter than */ { /* the basic range. */ d = ocd; continue; @@ -3562,6 +3825,7 @@ for (;; ptr++) skipbytes = 0; bravalue = OP_CBRA; save_hwm = cd->hwm; + reset_bracount = FALSE; if (*(++ptr) == '?') { @@ -3584,6 +3848,11 @@ for (;; ptr++) /* ------------------------------------------------------------ */ + case '|': /* Reset capture count for each branch */ + reset_bracount = TRUE; + /* Fall through */ + + /* ------------------------------------------------------------ */ case ':': /* Non-capturing bracket */ bravalue = OP_BRA; ptr++; @@ -3619,6 +3888,7 @@ for (;; ptr++) code[1+LINK_SIZE] = OP_CREF; skipbytes = 3; + refsign = -1; /* Check for a test for recursion in a named group. */ @@ -3642,7 +3912,11 @@ for (;; ptr++) terminator = '\''; ptr++; } - else terminator = 0; + else + { + terminator = 0; + if (ptr[1] == '-' || ptr[1] == '+') refsign = *(++ptr); + } /* We now expect to read a name; any thing else is an error */ @@ -3678,7 +3952,32 @@ for (;; ptr++) if (lengthptr != NULL) break; /* In the real compile we do the work of looking for the actual - reference. */ + reference. If the string started with "+" or "-" we require the rest to + be digits, in which case recno will be set. */ + + if (refsign > 0) + { + if (recno <= 0) + { + *errorcodeptr = ERR58; + goto FAILED; + } + if (refsign == '-') + { + recno = cd->bracount - recno + 1; + if (recno <= 0) + { + *errorcodeptr = ERR15; + goto FAILED; + } + } + else recno += cd->bracount; + PUT2(code, 2+LINK_SIZE, recno); + break; + } + + /* Otherwise (did not start with "+" or "-"), start by looking for the + name. */ slot = cd->name_table; for (i = 0; i < cd->names_found; i++) @@ -3997,19 +4296,54 @@ for (;; ptr++) /* ------------------------------------------------------------ */ + case '-': case '+': case '0': case '1': case '2': case '3': case '4': /* Recursion or */ case '5': case '6': case '7': case '8': case '9': /* subroutine */ { const uschar *called; + + if ((refsign = *ptr) == '+') ptr++; + else if (refsign == '-') + { + if ((digitab[ptr[1]] & ctype_digit) == 0) + goto OTHER_CHAR_AFTER_QUERY; + ptr++; + } + recno = 0; while((digitab[*ptr] & ctype_digit) != 0) recno = recno * 10 + *ptr++ - '0'; + if (*ptr != ')') { *errorcodeptr = ERR29; goto FAILED; } + if (refsign == '-') + { + if (recno == 0) + { + *errorcodeptr = ERR58; + goto FAILED; + } + recno = cd->bracount - recno + 1; + if (recno <= 0) + { + *errorcodeptr = ERR15; + goto FAILED; + } + } + else if (refsign == '+') + { + if (recno == 0) + { + *errorcodeptr = ERR58; + goto FAILED; + } + recno += cd->bracount; + } + /* Come here from code above that handles a named recursion */ HANDLE_RECURSION: @@ -4082,6 +4416,7 @@ for (;; ptr++) /* ------------------------------------------------------------ */ default: /* Other characters: check option setting */ + OTHER_CHAR_AFTER_QUERY: set = unset = 0; optset = &set; @@ -4216,6 +4551,7 @@ for (;; ptr++) 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 */ &subfirstbyte, /* For possible first char */ &subreqbyte, /* For possible last char */ @@ -4232,9 +4568,11 @@ for (;; 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. */ + 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) + if (bravalue == OP_COND && lengthptr == NULL) { uschar *tc = code; int condcount = 0; @@ -4394,12 +4732,13 @@ for (;; ptr++) zerofirstbyte = firstbyte; zeroreqbyte = reqbyte; - /* \k<name> or \k'name' is a back reference by name (Perl syntax) */ + /* \k<name> or \k'name' is a back reference by name (Perl syntax). + We also support \k{name} (.NET syntax) */ - if (-c == ESC_k && (ptr[1] == '<' || ptr[1] == '\'')) + if (-c == ESC_k && (ptr[1] == '<' || ptr[1] == '\'' || ptr[1] == '{')) { is_recurse = FALSE; - terminator = (*(++ptr) == '<')? '>' : '\''; + terminator = (*(++ptr) == '<')? '>' : (*ptr == '\'')? '\'' : '}'; goto NAMED_REF_OR_RECURSE; } @@ -4565,13 +4904,14 @@ 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. -Argument: +Arguments: options option bits, including any changes for this subpattern oldims previous settings of ims option bits 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) firstbyteptr place to put the first required character, or a negative number reqbyteptr place to put the last required character, or a negative number @@ -4585,8 +4925,9 @@ Returns: TRUE on success static BOOL compile_regex(int options, int oldims, uschar **codeptr, const uschar **ptrptr, - int *errorcodeptr, BOOL lookbehind, int skipbytes, int *firstbyteptr, - int *reqbyteptr, branch_chain *bcptr, compile_data *cd, int *lengthptr) + int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes, + int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd, + int *lengthptr) { const uschar *ptr = *ptrptr; uschar *code = *codeptr; @@ -4596,6 +4937,8 @@ uschar *reverse_count = NULL; int firstbyte, reqbyte; int branchfirstbyte, branchreqbyte; int length; +int orig_bracount; +int max_bracount; branch_chain bc; bc.outer = bcptr; @@ -4624,8 +4967,14 @@ 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; + /* Handle a change of ims options at the start of the branch */ if ((options & PCRE_IMS) != oldims) @@ -4655,6 +5004,11 @@ for (;;) 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) @@ -4718,26 +5072,29 @@ for (;;) } } - /* Reached end of expression, either ')' or end of pattern. 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. If any of - the ims options were changed inside the group, compile a resetting op-code - following, except at the very end of the pattern. Return leaving the pointer - at the terminating char. */ + /* 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. If any of the ims options were changed inside the group, + compile a resetting op-code following, except at the very end of the pattern. + Return leaving the pointer at the terminating char. */ if (*ptr != '|') { - int branch_length = code - last_branch; - do + if (lengthptr == NULL) { - int prev_length = GET(last_branch, 1); - PUT(last_branch, 1, branch_length); - branch_length = prev_length; - last_branch -= branch_length; + int branch_length = 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); } - while (branch_length > 0); /* Fill in the ket */ @@ -4754,6 +5111,10 @@ for (;;) length += 2; } + /* Retain the highest bracket number, in case resetting was used. */ + + cd->bracount = max_bracount; + /* Set values to pass back */ *codeptr = code; @@ -4764,17 +5125,29 @@ for (;;) return TRUE; } - /* Another branch follows; insert an "or" node. Its length field points back + /* 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. */ - *code = OP_ALT; - PUT(code, 1, code - last_branch); - bc.current = last_branch = code; - code += 1 + LINK_SIZE; + if (lengthptr != NULL) + { + code = *codeptr + 1 + LINK_SIZE + skipbytes; + length += 1 + LINK_SIZE; + } + else + { + *code = OP_ALT; + PUT(code, 1, code - last_branch); + bc.current = last_branch = code; + code += 1 + LINK_SIZE; + } + ptr++; - length += 1 + LINK_SIZE; } /* Control never reaches here */ } @@ -5041,7 +5414,7 @@ Returns: pointer to compiled data block, or NULL on error, with errorptr and erroroffset set */ -PCRE_DATA_SCOPE pcre * +PCRE_EXP_DEFN pcre * pcre_compile(const char *pattern, int options, const char **errorptr, int *erroroffset, const unsigned char *tables) { @@ -5049,7 +5422,7 @@ return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables); } -PCRE_DATA_SCOPE pcre * +PCRE_EXP_DEFN pcre * pcre_compile2(const char *pattern, int options, int *errorcodeptr, const char **errorptr, int *erroroffset, const unsigned char *tables) { @@ -5098,7 +5471,7 @@ if (errorcodeptr != NULL) *errorcodeptr = ERR0; if (erroroffset == NULL) { errorcode = ERR16; - goto PCRE_EARLY_ERROR_RETURN; + goto PCRE_EARLY_ERROR_RETURN2; } *erroroffset = 0; @@ -5111,7 +5484,7 @@ if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0 && (*erroroffset = _pcre_valid_utf8((uschar *)pattern, -1)) >= 0) { errorcode = ERR44; - goto PCRE_UTF8_ERROR_RETURN; + goto PCRE_EARLY_ERROR_RETURN2; } #else if ((options & PCRE_UTF8) != 0) @@ -5136,7 +5509,8 @@ cd->cbits = tables + cbits_offset; cd->ctypes = tables + ctypes_offset; /* Handle different types of newline. The three bits give seven cases. The -current code allows for fixed one- or two-byte sequences, plus "any". */ +current code allows for fixed one- or two-byte sequences, plus "any" and +"anycrlf". */ switch (options & (PCRE_NEWLINE_CRLF | PCRE_NEWLINE_ANY)) { @@ -5146,10 +5520,15 @@ switch (options & (PCRE_NEWLINE_CRLF | PCRE_NEWLINE_ANY)) case PCRE_NEWLINE_CR+ PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; 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 < 0) +if (newline == -2) + { + cd->nltype = NLTYPE_ANYCRLF; + } +else if (newline < 0) { cd->nltype = NLTYPE_ANY; } @@ -5210,7 +5589,8 @@ outside can help speed up starting point checks. */ code = cworkspace; *code = OP_BRA; (void)compile_regex(cd->external_options, cd->external_options & PCRE_IMS, - &code, &ptr, &errorcode, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, &length); + &code, &ptr, &errorcode, FALSE, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, + &length); if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN; DPRINTF(("end pre-compile: length=%d workspace=%d\n", length, @@ -5278,7 +5658,7 @@ ptr = (const uschar *)pattern; code = (uschar *)codestart; *code = OP_BRA; (void)compile_regex(re->options, re->options & PCRE_IMS, &code, &ptr, - &errorcode, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, NULL); + &errorcode, FALSE, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, NULL); re->top_bracket = cd->bracount; re->top_backref = cd->top_backref; @@ -5323,9 +5703,7 @@ if (errorcode != 0) (pcre_free)(re); PCRE_EARLY_ERROR_RETURN: *erroroffset = ptr - (const uschar *)pattern; -#ifdef SUPPORT_UTF8 - PCRE_UTF8_ERROR_RETURN: -#endif + PCRE_EARLY_ERROR_RETURN2: *errorptr = error_texts[errorcode]; if (errorcodeptr != NULL) *errorcodeptr = errorcode; return NULL; @@ -5415,7 +5793,7 @@ if ((re->options & PCRE_REQCHSET) != 0) else printf("Req char = \\x%02x%s\n", ch, caseless); } -pcre_printint(re, stdout); +pcre_printint(re, stdout, TRUE); /* This check is done here in the debugging case so that the code that was compiled can be seen. */ diff --git a/src/src/pcre/pcre_config.c b/src/src/pcre/pcre_config.c index 582cf4a81..ff8cdf89a 100644 --- a/src/src/pcre/pcre_config.c +++ b/src/src/pcre/pcre_config.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_config.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_config.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -60,7 +60,7 @@ Arguments: Returns: 0 if data returned, negative on error */ -PCRE_DATA_SCOPE int +PCRE_EXP_DEFN int pcre_config(int what, void *where) { switch (what) diff --git a/src/src/pcre/pcre_exec.c b/src/src/pcre/pcre_exec.c index 27cd52fec..a27835d74 100644 --- a/src/src/pcre/pcre_exec.c +++ b/src/src/pcre/pcre_exec.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_exec.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_exec.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -50,6 +50,11 @@ possible. There are also some static supporting functions. */ #include "pcre_internal.h" +/* Undefine some potentially clashing cpp symbols */ + +#undef min +#undef max + /* The chain of eptrblocks for tail recursions uses memory in stack workspace, obtained at top level, the size of which is defined by EPTR_WORK_SIZE. */ @@ -185,20 +190,45 @@ 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 */ + +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 }; + + /* These versions of the macros use the stack, as normal. There are debugging -versions and production versions. */ +versions and production versions. Note that the "rw" argument of RMATCH isn't +actuall used in this definition. */ #ifndef NO_RECURSE #define REGISTER register + #ifdef DEBUG -#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg) \ +#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \ { \ printf("match() called in line %d\n", __LINE__); \ - rx = match(ra,rb,rc,rd,re,rf,rg,rdepth+1); \ + rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1); \ printf("to line %d\n", __LINE__); \ } #define RRETURN(ra) \ @@ -207,43 +237,38 @@ versions and production versions. */ return ra; \ } #else -#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg) \ - rx = match(ra,rb,rc,rd,re,rf,rg,rdepth+1) +#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \ + rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,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. It's the md argument of -match(), which never changes. */ +/* 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(rx,ra,rb,rc,rd,re,rf,rg)\ +#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\ {\ heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\ - if (setjmp(frame->Xwhere) == 0)\ - {\ - newframe->Xeptr = ra;\ - newframe->Xecode = rb;\ - newframe->Xoffset_top = rc;\ - newframe->Xims = re;\ - newframe->Xeptrb = rf;\ - newframe->Xflags = rg;\ - newframe->Xrdepth = frame->Xrdepth + 1;\ - newframe->Xprevframe = frame;\ - frame = newframe;\ - DPRINTF(("restarting from line %d\n", __LINE__));\ - goto HEAP_RECURSE;\ - }\ - else\ - {\ - DPRINTF(("longjumped back to line %d\n", __LINE__));\ - frame = md->thisframe;\ - rx = frame->Xresult;\ - }\ + frame->Xwhere = rw; \ + newframe->Xeptr = ra;\ + newframe->Xecode = rb;\ + newframe->Xmstart = mstart;\ + newframe->Xoffset_top = rc;\ + newframe->Xims = re;\ + newframe->Xeptrb = rf;\ + newframe->Xflags = rg;\ + 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)\ @@ -253,9 +278,8 @@ match(), which never changes. */ (pcre_stack_free)(newframe);\ if (frame != NULL)\ {\ - frame->Xresult = ra;\ - md->thisframe = frame;\ - longjmp(frame->Xwhere, 1);\ + rrc = ra;\ + goto HEAP_RETURN;\ }\ return ra;\ } @@ -270,6 +294,7 @@ typedef struct heapframe { const uschar *Xeptr; const uschar *Xecode; + const uschar *Xmstart; int Xoffset_top; long int Xims; eptrblock *Xeptrb; @@ -301,6 +326,8 @@ typedef struct heapframe { int Xprop_category; int Xprop_chartype; int Xprop_script; + int Xoclength; + uschar Xocchars[8]; #endif int Xctype; @@ -318,10 +345,9 @@ typedef struct heapframe { eptrblock Xnewptrb; - /* Place to pass back result, and where to jump back to */ + /* Where to jump back to */ - int Xresult; - jmp_buf Xwhere; + int Xwhere; } heapframe; @@ -349,6 +375,8 @@ 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 ims current /i, /m, and /s options @@ -368,7 +396,7 @@ Returns: MATCH_MATCH if matched ) these values are >= 0 */ static int -match(REGISTER USPTR eptr, REGISTER const uschar *ecode, +match(REGISTER USPTR eptr, REGISTER const uschar *ecode, const uschar *mstart, int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb, int flags, unsigned int rdepth) { @@ -396,6 +424,7 @@ frame->Xprevframe = NULL; /* Marks the top level */ frame->Xeptr = eptr; frame->Xecode = ecode; +frame->Xmstart = mstart; frame->Xoffset_top = offset_top; frame->Xims = ims; frame->Xeptrb = eptrb; @@ -410,6 +439,7 @@ HEAP_RECURSE: #define eptr frame->Xeptr #define ecode frame->Xecode +#define mstart frame->Xmstart #define offset_top frame->Xoffset_top #define ims frame->Xims #define eptrb frame->Xeptrb @@ -443,6 +473,8 @@ HEAP_RECURSE: #define prop_category frame->Xprop_category #define prop_chartype frame->Xprop_chartype #define prop_script frame->Xprop_script +#define oclength frame->Xoclength +#define occhars frame->Xocchars #endif #define ctype frame->Xctype @@ -496,6 +528,8 @@ int prop_fail_result; int prop_category; int prop_chartype; int prop_script; +int oclength; +uschar occhars[8]; #endif int ctype; @@ -536,6 +570,12 @@ 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_UTF8 +utf8 = md->utf8; /* Local copy of the flag */ +#else +utf8 = FALSE; +#endif + /* First check that we haven't called match() too many times, or that we haven't exceeded the recursive call limit. */ @@ -544,12 +584,6 @@ if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT); original_ims = ims; /* Save for resetting on ')' */ -#ifdef SUPPORT_UTF8 -utf8 = md->utf8; /* Local copy of the flag */ -#else -utf8 = FALSE; -#endif - /* At the start of a group with an unlimited repeat that may match an empty string, the match_cbegroup flag is set. When this is the case, add the current subject pointer to the chain of such remembered pointers, to be checked when we @@ -584,7 +618,7 @@ for (;;) if (md->partial && eptr >= md->end_subject && - eptr > md->start_match) + eptr > mstart) md->hitend = TRUE; switch(op) @@ -628,8 +662,8 @@ for (;;) flags = (op == OP_SCBRA)? match_cbegroup : 0; do { - RMATCH(rrc, eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, - ims, eptrb, flags); + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, + ims, eptrb, flags, RM1); if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->capture_last = save_capture_last; ecode += GET(ecode, 1); @@ -672,8 +706,8 @@ for (;;) /* For non-final alternatives, continue the loop for a NOMATCH result; otherwise return. */ - RMATCH(rrc, eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims, - eptrb, flags); + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims, + eptrb, flags, RM2); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += GET(ecode, 1); } @@ -714,8 +748,8 @@ for (;;) else { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, - match_condassert); + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_condassert, RM3); if (rrc == MATCH_MATCH) { condition = TRUE; @@ -761,7 +795,7 @@ for (;;) md->recursive = rec->prevrec; memmove(md->offset_vector, rec->offset_save, rec->saved_max * sizeof(int)); - md->start_match = rec->save_start; + mstart = rec->save_start; ims = original_ims; ecode = rec->after_call; break; @@ -770,9 +804,10 @@ for (;;) /* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty string - backtracking will then try other alternatives, if any. */ - if (md->notempty && eptr == md->start_match) RRETURN(MATCH_NOMATCH); - md->end_match_ptr = eptr; /* Record where we ended */ - md->end_offset_top = offset_top; /* and how many extracts were taken */ + if (md->notempty && eptr == mstart) RRETURN(MATCH_NOMATCH); + 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) */ RRETURN(MATCH_MATCH); /* Change option settings */ @@ -793,7 +828,8 @@ for (;;) case OP_ASSERTBACK: do { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0); + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0, + RM4); if (rrc == MATCH_MATCH) break; if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += GET(ecode, 1); @@ -819,7 +855,8 @@ for (;;) case OP_ASSERTBACK_NOT: do { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0); + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0, + RM5); if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += GET(ecode,1); @@ -876,7 +913,7 @@ for (;;) cb.offset_vector = md->offset_vector; cb.subject = (PCRE_SPTR)md->start_subject; cb.subject_length = md->end_subject - md->start_subject; - cb.start_match = md->start_match - md->start_subject; + cb.start_match = mstart - md->start_subject; cb.current_position = eptr - md->start_subject; cb.pattern_position = GET(ecode, 2); cb.next_item_length = GET(ecode, 2 + LINK_SIZE); @@ -938,8 +975,8 @@ for (;;) memcpy(new_recursive.offset_save, md->offset_vector, new_recursive.saved_max * sizeof(int)); - new_recursive.save_start = md->start_match; - md->start_match = eptr; + new_recursive.save_start = mstart; + mstart = eptr; /* OK, now we can do the recursion. For each top-level alternative we restore the offset and recursion data. */ @@ -948,8 +985,8 @@ for (;;) flags = (*callpat >= OP_SBRA)? match_cbegroup : 0; do { - RMATCH(rrc, eptr, callpat + _pcre_OP_lengths[*callpat], offset_top, - md, ims, eptrb, flags); + RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top, + md, ims, eptrb, flags, RM6); if (rrc == MATCH_MATCH) { DPRINTF(("Recursion matched\n")); @@ -992,8 +1029,8 @@ for (;;) do { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, - eptrb, 0); + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, 0, RM7); if (rrc == MATCH_MATCH) break; if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += GET(ecode,1); @@ -1038,7 +1075,8 @@ for (;;) if (*ecode == OP_KETRMIN) { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, + RM8); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode = prev; flags = match_tail_recursed; @@ -1046,7 +1084,7 @@ for (;;) } else /* OP_KETRMAX */ { - RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_cbegroup); + RMATCH(eptr, prev, offset_top, md, ims, eptrb, match_cbegroup, RM9); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += 1 + LINK_SIZE; flags = match_tail_recursed; @@ -1070,7 +1108,7 @@ for (;;) case OP_BRAZERO: { next = ecode+1; - RMATCH(rrc, eptr, next, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, next, offset_top, md, ims, eptrb, 0, RM10); if (rrc != MATCH_NOMATCH) RRETURN(rrc); do next += GET(next,1); while (*next == OP_ALT); ecode = next + 1 + LINK_SIZE; @@ -1081,7 +1119,7 @@ for (;;) { next = ecode+1; do next += GET(next, 1); while (*next == OP_ALT); - RMATCH(rrc, eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0, RM11); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode++; } @@ -1151,7 +1189,7 @@ for (;;) recursion_info *rec = md->recursive; DPRINTF(("Recursion (%d) succeeded - continuing\n", number)); md->recursive = rec->prevrec; - md->start_match = rec->save_start; + mstart = rec->save_start; memcpy(md->offset_vector, rec->offset_save, rec->saved_max * sizeof(int)); ecode = rec->after_call; @@ -1186,7 +1224,8 @@ for (;;) if (*ecode == OP_KETRMIN) { - RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0, + RM12); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode = prev; flags |= match_tail_recursed; @@ -1194,7 +1233,7 @@ for (;;) } else /* OP_KETRMAX */ { - RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, flags); + RMATCH(eptr, prev, offset_top, md, ims, eptrb, flags, RM13); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += 1 + LINK_SIZE; flags = match_tail_recursed; @@ -1230,6 +1269,13 @@ for (;;) ecode++; break; + /* Reset the start of match point */ + + case OP_SET_SOM: + mstart = eptr; + ecode++; + break; + /* Assert before internal newline if multiline, or before a terminating newline unless endonly is set, else end of subject unless noteol is set. */ @@ -1438,6 +1484,102 @@ for (;;) ecode++; break; + case OP_NOT_HSPACE: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + 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 */ + RRETURN(MATCH_NOMATCH); + } + ecode++; + break; + + case OP_HSPACE: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + 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 */ + break; + } + ecode++; + break; + + case OP_NOT_VSPACE: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + switch(c) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + RRETURN(MATCH_NOMATCH); + } + ecode++; + break; + + case OP_VSPACE: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + break; + } + 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. */ @@ -1593,7 +1735,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || !match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); @@ -1614,7 +1756,7 @@ for (;;) } while (eptr >= pp) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM15); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr -= length; } @@ -1719,7 +1861,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); GETCHARINC(c, eptr); @@ -1739,7 +1881,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); c = *eptr++; @@ -1776,7 +1918,7 @@ for (;;) } for (;;) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM18); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- == pp) break; /* Stop if tried at original pos */ BACKCHAR(eptr); @@ -1795,7 +1937,7 @@ for (;;) } while (eptr >= pp) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM19); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; } @@ -1866,7 +2008,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); GETCHARINC(c, eptr); @@ -1890,7 +2032,7 @@ for (;;) } for(;;) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM21); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- == pp) break; /* Stop if tried at original pos */ BACKCHAR(eptr) @@ -2047,19 +2189,18 @@ for (;;) if (length > 1) { - int oclength = 0; - uschar occhars[8]; - #ifdef SUPPORT_UCP unsigned int othercase; if ((ims & PCRE_CASELESS) != 0 && (othercase = _pcre_ucp_othercase(fc)) != NOTACHAR) oclength = _pcre_ord2utf8(othercase, occhars); + else oclength = 0; #endif /* SUPPORT_UCP */ for (i = 1; i <= min; i++) { if (memcmp(eptr, charptr, length) == 0) eptr += length; +#ifdef SUPPORT_UCP /* Need braces because of following else */ else if (oclength == 0) { RRETURN(MATCH_NOMATCH); } else @@ -2067,6 +2208,9 @@ for (;;) if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH); eptr += oclength; } +#else /* without SUPPORT_UCP */ + else { RRETURN(MATCH_NOMATCH); } +#endif /* SUPPORT_UCP */ } if (min == max) continue; @@ -2075,10 +2219,11 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); if (memcmp(eptr, charptr, length) == 0) eptr += length; +#ifdef SUPPORT_UCP /* Need braces because of following else */ else if (oclength == 0) { RRETURN(MATCH_NOMATCH); } else @@ -2086,6 +2231,9 @@ for (;;) if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH); eptr += oclength; } +#else /* without SUPPORT_UCP */ + else { RRETURN (MATCH_NOMATCH); } +#endif /* SUPPORT_UCP */ } /* Control never gets here */ } @@ -2097,22 +2245,31 @@ for (;;) { if (eptr > md->end_subject - length) break; if (memcmp(eptr, charptr, length) == 0) eptr += length; +#ifdef SUPPORT_UCP else if (oclength == 0) break; else { if (memcmp(eptr, occhars, oclength) != 0) break; eptr += oclength; } +#else /* without SUPPORT_UCP */ + else break; +#endif /* SUPPORT_UCP */ } if (possessive) continue; - while (eptr >= pp) + for(;;) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23); if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr == pp) RRETURN(MATCH_NOMATCH); +#ifdef SUPPORT_UCP + eptr--; + BACKCHAR(eptr); +#else /* without SUPPORT_UCP */ eptr -= length; +#endif /* SUPPORT_UCP */ } - RRETURN(MATCH_NOMATCH); } /* Control never gets here */ } @@ -2152,7 +2309,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject || fc != md->lcc[*eptr++]) @@ -2171,7 +2328,7 @@ for (;;) if (possessive) continue; while (eptr >= pp) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25); eptr--; if (rrc != MATCH_NOMATCH) RRETURN(rrc); } @@ -2190,7 +2347,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject || fc != *eptr++) RRETURN(MATCH_NOMATCH); @@ -2208,7 +2365,7 @@ for (;;) if (possessive) continue; while (eptr >= pp) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27); eptr--; if (rrc != MATCH_NOMATCH) RRETURN(rrc); } @@ -2353,7 +2510,7 @@ for (;;) register unsigned int d; for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28); if (rrc != MATCH_NOMATCH) RRETURN(rrc); GETCHARINC(d, eptr); if (d < 256) d = md->lcc[d]; @@ -2367,7 +2524,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); @@ -2399,7 +2556,7 @@ for (;;) if (possessive) continue; for(;;) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM30); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- == pp) break; /* Stop if tried at original pos */ BACKCHAR(eptr); @@ -2417,7 +2574,7 @@ for (;;) if (possessive) continue; while (eptr >= pp) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM31); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; } @@ -2462,7 +2619,7 @@ for (;;) register unsigned int d; for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32); if (rrc != MATCH_NOMATCH) RRETURN(rrc); GETCHARINC(d, eptr); if (fi >= max || eptr >= md->end_subject || fc == d) @@ -2475,7 +2632,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject || fc == *eptr++) RRETURN(MATCH_NOMATCH); @@ -2506,7 +2663,7 @@ for (;;) if (possessive) continue; for(;;) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM34); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- == pp) break; /* Stop if tried at original pos */ BACKCHAR(eptr); @@ -2524,7 +2681,7 @@ for (;;) if (possessive) continue; while (eptr >= pp) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM35); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; } @@ -2631,7 +2788,7 @@ for (;;) for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); + GETCHARINCTEST(c, eptr); } break; @@ -2639,7 +2796,7 @@ for (;;) for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); + GETCHARINCTEST(c, eptr); prop_category = _pcre_ucp_findprop(c, &prop_chartype, &prop_script); if ((prop_chartype == ucp_Lu || prop_chartype == ucp_Ll || @@ -2652,7 +2809,7 @@ for (;;) for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); + GETCHARINCTEST(c, eptr); prop_category = _pcre_ucp_findprop(c, &prop_chartype, &prop_script); if ((prop_category == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); @@ -2663,7 +2820,7 @@ for (;;) for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); + GETCHARINCTEST(c, eptr); prop_category = _pcre_ucp_findprop(c, &prop_chartype, &prop_script); if ((prop_chartype == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); @@ -2674,7 +2831,7 @@ for (;;) for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); + GETCHARINCTEST(c, eptr); prop_category = _pcre_ucp_findprop(c, &prop_chartype, &prop_script); if ((prop_script == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); @@ -2755,6 +2912,110 @@ for (;;) } break; + case OP_NOT_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + 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 */ + RRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + 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 */ + break; + } + } + break; + + case OP_NOT_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + switch(c) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + RRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + break; + } + } + break; + case OP_NOT_DIGIT: for (i = 1; i <= min; i++) { @@ -2866,6 +3127,70 @@ for (;;) } break; + case OP_NOT_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + switch(*eptr++) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + RRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + switch(*eptr++) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + break; + } + } + break; + + case OP_NOT_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + switch(*eptr++) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + RRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + switch(*eptr++) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + break; + } + } + break; + case OP_NOT_DIGIT: for (i = 1; i <= min; i++) if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); @@ -2921,7 +3246,7 @@ for (;;) case PT_ANY: for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); GETCHARINC(c, eptr); @@ -2932,7 +3257,7 @@ for (;;) case PT_LAMP: for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); GETCHARINC(c, eptr); @@ -2947,7 +3272,7 @@ for (;;) case PT_GC: for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); GETCHARINC(c, eptr); @@ -2960,7 +3285,7 @@ for (;;) case PT_PC: for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); GETCHARINC(c, eptr); @@ -2973,7 +3298,7 @@ for (;;) case PT_SC: for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); GETCHARINC(c, eptr); @@ -2995,7 +3320,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); GETCHARINCTEST(c, eptr); @@ -3024,7 +3349,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject || (ctype == OP_ANY && (ims & PCRE_DOTALL) == 0 && @@ -3057,6 +3382,90 @@ for (;;) } break; + case OP_NOT_HSPACE: + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + 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 */ + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_HSPACE: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + 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 */ + break; + } + break; + + case OP_NOT_VSPACE: + switch(c) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_VSPACE: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + break; + } + break; + case OP_NOT_DIGIT: if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); @@ -3098,7 +3507,7 @@ for (;;) { for (fi = min;; fi++) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max || eptr >= md->end_subject || ((ims & PCRE_DOTALL) == 0 && IS_NEWLINE(eptr))) @@ -3128,6 +3537,54 @@ for (;;) } break; + case OP_NOT_HSPACE: + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_HSPACE: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + break; + } + break; + + case OP_NOT_VSPACE: + switch(c) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_VSPACE: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + break; + } + break; + case OP_NOT_DIGIT: if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); break; @@ -3244,7 +3701,7 @@ for (;;) if (possessive) continue; for(;;) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM44); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- == pp) break; /* Stop if tried at original pos */ BACKCHAR(eptr); @@ -3280,7 +3737,7 @@ for (;;) if (possessive) continue; for(;;) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM45); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- == pp) break; /* Stop if tried at original pos */ for (;;) /* Move back over one extended */ @@ -3389,6 +3846,70 @@ for (;;) } break; + case OP_NOT_HSPACE: + case OP_HSPACE: + for (i = min; i < max; i++) + { + BOOL gotspace; + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + switch(c) + { + default: gotspace = FALSE; break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + 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 */ + gotspace = TRUE; + 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) break; + GETCHARLEN(c, eptr, len); + switch(c) + { + default: gotspace = FALSE; break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + gotspace = TRUE; + break; + } + if (gotspace == (ctype == OP_NOT_VSPACE)) break; + eptr += len; + } + break; + case OP_NOT_DIGIT: for (i = min; i < max; i++) { @@ -3464,7 +3985,7 @@ for (;;) if (possessive) continue; for(;;) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM46); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- == pp) break; /* Stop if tried at original pos */ BACKCHAR(eptr); @@ -3515,6 +4036,48 @@ for (;;) } break; + case OP_NOT_HSPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + c = *eptr; + if (c == 0x09 || c == 0x20 || c == 0xa0) break; + eptr++; + } + break; + + case OP_HSPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + c = *eptr; + if (c != 0x09 && c != 0x20 && c != 0xa0) break; + eptr++; + } + break; + + case OP_NOT_VSPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + c = *eptr; + if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85) + break; + eptr++; + } + break; + + case OP_VSPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + c = *eptr; + if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85) + break; + eptr++; + } + break; + case OP_NOT_DIGIT: for (i = min; i < max; i++) { @@ -3578,7 +4141,7 @@ for (;;) if (possessive) continue; while (eptr >= pp) { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM47); eptr--; if (rrc != MATCH_NOMATCH) RRETURN(rrc); } @@ -3604,6 +4167,29 @@ for (;;) } /* 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(16) + LBL(17) LBL(18) LBL(19) LBL(20) LBL(21) LBL(22) LBL(23) LBL(24) + LBL(25) LBL(26) LBL(27) LBL(28) LBL(29) LBL(30) LBL(31) LBL(32) + LBL(33) LBL(34) LBL(35) LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) + LBL(41) LBL(42) LBL(43) LBL(44) LBL(45) LBL(46) LBL(47) + default: + DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere)); + return PCRE_ERROR_INTERNAL; + } +#undef LBL +#endif /* NO_RECURSE */ } @@ -3616,6 +4202,7 @@ Undefine all the macros that were defined above to handle this. */ #ifdef NO_RECURSE #undef eptr #undef ecode +#undef mstart #undef offset_top #undef ims #undef eptrb @@ -3688,7 +4275,7 @@ Returns: > 0 => success; value is the number of elements filled in < -1 => some kind of unexpected problem */ -PCRE_DATA_SCOPE int +PCRE_EXP_DEFN int 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) @@ -3804,10 +4391,10 @@ md->eptrchain = eptrchain; /* Make workspace generally available */ md->lcc = tables + lcc_offset; md->ctypes = tables + ctypes_offset; -/* Handle different types of newline. The two bits give four cases. If nothing -is set at run time, whatever was used at compile time applies. */ +/* 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 : options) & +switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) & PCRE_NEWLINE_BITS) { case 0: newline = NEWLINE; break; /* Compile-time default */ @@ -3816,10 +4403,15 @@ switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : options) & case PCRE_NEWLINE_CR+ PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break; case PCRE_NEWLINE_ANY: newline = -1; break; + case PCRE_NEWLINE_ANYCRLF: newline = -2; break; default: return PCRE_ERROR_BADNEWLINE; } -if (newline < 0) +if (newline == -2) + { + md->nltype = NLTYPE_ANYCRLF; + } +else if (newline < 0) { md->nltype = NLTYPE_ANY; } @@ -3994,6 +4586,16 @@ for(;;) { 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] == '\r' && + (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && + start_match < end_subject && + *start_match == '\n') + start_match++; } } @@ -4080,10 +4682,11 @@ for(;;) /* OK, we can now run the match. */ - md->start_match = start_match; + md->start_match_ptr = start_match; /* Insurance */ md->match_call_count = 0; md->eptrn = 0; /* Next free eptrchain slot */ - rc = match(start_match, md->start_code, 2, md, ims, NULL, 0, 0); + rc = match(start_match, md->start_code, start_match, 2, md, + ims, NULL, 0, 0); /* Any return other than MATCH_NOMATCH breaks the loop. */ @@ -4109,11 +4712,14 @@ for(;;) if (anchored || start_match > end_subject) break; - /* If we have just passed a CR and the newline option is CRLF or ANY, and we - are now at a LF, advance the match position by one more character. */ + /* If we have just passed a CR and the newline option is CRLF or ANY or + ANYCRLF, and we are now at a LF, advance the match position by one more + character. */ if (start_match[-1] == '\r' && - (md->nltype == NLTYPE_ANY || md->nllen == 2) && + (md->nltype == NLTYPE_ANY || + md->nltype == NLTYPE_ANYCRLF || + md->nllen == 2) && start_match < end_subject && *start_match == '\n') start_match++; @@ -4160,11 +4766,13 @@ if (rc == MATCH_MATCH) rc = md->offset_overflow? 0 : md->end_offset_top/2; - /* If there is space, set up the whole thing as substring 0. */ + /* 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] = start_match - md->start_subject; + offsets[0] = md->start_match_ptr - md->start_subject; offsets[1] = md->end_match_ptr - md->start_subject; } diff --git a/src/src/pcre/pcre_fullinfo.c b/src/src/pcre/pcre_fullinfo.c index 5eddcd71e..c17f3d72b 100644 --- a/src/src/pcre/pcre_fullinfo.c +++ b/src/src/pcre/pcre_fullinfo.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_fullinfo.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_fullinfo.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -63,7 +63,7 @@ Arguments: Returns: 0 if data returned, negative on error */ -PCRE_DATA_SCOPE int +PCRE_EXP_DEFN int pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, int what, void *where) { @@ -142,6 +142,14 @@ switch (what) *((const uschar **)where) = (const uschar *)(_pcre_default_tables); break; + case PCRE_INFO_OKPARTIAL: + *((int *)where) = (re->options & PCRE_NOPARTIAL) == 0; + break; + + case PCRE_INFO_JCHANGED: + *((int *)where) = (re->options & PCRE_JCHANGED) != 0; + break; + default: return PCRE_ERROR_BADOPTION; } diff --git a/src/src/pcre/pcre_get.c b/src/src/pcre/pcre_get.c index 0dcd5d69b..3added96d 100644 --- a/src/src/pcre/pcre_get.c +++ b/src/src/pcre/pcre_get.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_get.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_get.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without diff --git a/src/src/pcre/pcre_globals.c b/src/src/pcre/pcre_globals.c index 2c3a80b67..ee3707d9d 100644 --- a/src/src/pcre/pcre_globals.c +++ b/src/src/pcre/pcre_globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_globals.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_globals.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -48,37 +48,14 @@ indirection. These values can be changed by the caller, but are shared between all threads. However, when compiling for Virtual Pascal, things are done differently, and global variables are not used (see pcre.in). */ - #include "pcre_internal.h" - #ifndef VPCOMPAT - -/************************************************************************** -This code used to be here for use when compiling as a C++ library. However, -according to Dair Grant it is not needed: " - - Including 'extern "C"' in the declaration generates an "initialized and - declared `extern'" warning from gcc 4.0.1. Since we include pcre_internal.h, - which includes pcre.h, which declares these prototypes within an extern "C" {} - block, we shouldn't need the prefix here. - -So, from Release 7.0 I have cut this out. - -#ifdef __cplusplus -extern "C" void *(*pcre_malloc)(size_t) = malloc; -extern "C" void (*pcre_free)(void *) = free; -extern "C" void *(*pcre_stack_malloc)(size_t) = malloc; -extern "C" void (*pcre_stack_free)(void *) = free; -extern "C" int (*pcre_callout)(pcre_callout_block *) = NULL; -#else -**************************************************************************/ - -void *(*pcre_malloc)(size_t) = malloc; -void (*pcre_free)(void *) = free; -void *(*pcre_stack_malloc)(size_t) = malloc; -void (*pcre_stack_free)(void *) = free; -int (*pcre_callout)(pcre_callout_block *) = NULL; +PCRE_EXP_DATA_DEFN void *(*pcre_malloc)(size_t) = malloc; +PCRE_EXP_DATA_DEFN void (*pcre_free)(void *) = free; +PCRE_EXP_DATA_DEFN void *(*pcre_stack_malloc)(size_t) = malloc; +PCRE_EXP_DATA_DEFN void (*pcre_stack_free)(void *) = free; +PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL; #endif /* End of pcre_globals.c */ diff --git a/src/src/pcre/pcre_internal.h b/src/src/pcre/pcre_internal.h index 20172832f..e2a55b120 100644 --- a/src/src/pcre/pcre_internal.h +++ b/src/src/pcre/pcre_internal.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_internal.h,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_internal.h,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -9,7 +9,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -85,8 +85,58 @@ setjmp and stdarg are used is when NO_RECURSE is set. */ #include <stdlib.h> #include <string.h> -#ifndef PCRE_SPY -#define PCRE_DEFINITION /* Win32 __declspec(export) trigger for .dll */ +/* 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 +# ifdef DLL_EXPORT +# 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 /* We need to have types that specify unsigned 16-bit and 32-bit integers. We @@ -127,21 +177,22 @@ characters only go up to 0x7fffffff (though Unicode doesn't go beyond #define NOTACHAR 0xffffffff /* PCRE is able to support several different kinds of newline (CR, LF, CRLF, -and "all" 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. */ +"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_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 && \ - _pcre_is_newline((p), NLBLOCK->PSEND, &(NLBLOCK->nllen), utf8) \ - ) \ + _pcre_is_newline((p), NLBLOCK->nltype, NLBLOCK->PSEND, &(NLBLOCK->nllen),\ + utf8)) \ : \ ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \ (p)[0] == NLBLOCK->nl[0] && \ @@ -154,8 +205,8 @@ string field names are. */ #define WAS_NEWLINE(p) \ ((NLBLOCK->nltype != NLTYPE_FIXED)? \ ((p) > NLBLOCK->PSSTART && \ - _pcre_was_newline((p), NLBLOCK->PSSTART, &(NLBLOCK->nllen), utf8) \ - ) \ + _pcre_was_newline((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \ + &(NLBLOCK->nllen), utf8)) \ : \ ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \ (p)[-NLBLOCK->nllen] == NLBLOCK->nl[0] && \ @@ -180,10 +231,12 @@ must begin with PCRE_. */ #define USPTR const unsigned char * #endif + + /* Include the public PCRE header and the definitions of UCP character property values. */ -#include "pcre.h" +#include <pcre.h> #include "ucp.h" /* When compiling for use with the Virtual Pascal compiler, these functions @@ -191,7 +244,9 @@ 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) @@ -200,23 +255,31 @@ option on the command line. */ /* 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). This assumes -that all calls to memmove are moving strings upwards in store, which is the -case in PCRE. */ +neither (there some non-Unix environments where this is the case). */ -#if ! HAVE_MEMMOVE +#ifndef HAVE_MEMMOVE #undef memmove /* some systems may have a macro */ -#if HAVE_BCOPY +#ifdef HAVE_BCOPY #define memmove(a, b, c) bcopy(b, a, c) #else /* HAVE_BCOPY */ static void * -pcre_memmove(unsigned char *dest, const unsigned char *src, size_t n) +pcre_memmove(void *d, const void *s, size_t n) { size_t i; -dest += n; -src += n; -for (i = 0; i < n; ++i) *(--dest) = *(--src); -return dest; +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 */ @@ -441,7 +504,8 @@ bits. */ /* 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) +#define PCRE_NEWLINE_BITS (PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_ANY| \ + PCRE_NEWLINE_ANYCRLF) #define PUBLIC_OPTIONS \ (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ @@ -543,9 +607,9 @@ 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_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, - ESC_w, ESC_dum1, ESC_C, ESC_P, ESC_p, ESC_R, ESC_X, ESC_Z, ESC_z, - ESC_E, ESC_Q, ESC_k, ESC_REF }; +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_dum1, 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_k, ESC_REF }; /* Opcode table: OP_BRA must be last, as all values >= it are used for brackets @@ -567,133 +631,138 @@ enum { OP_SOD, /* 1 Start of data: \A */ OP_SOM, /* 2 Start of match (subject + offset): \G */ - OP_NOT_WORD_BOUNDARY, /* 3 \B */ - OP_WORD_BOUNDARY, /* 4 \b */ - OP_NOT_DIGIT, /* 5 \D */ - OP_DIGIT, /* 6 \d */ - OP_NOT_WHITESPACE, /* 7 \S */ - OP_WHITESPACE, /* 8 \s */ - OP_NOT_WORDCHAR, /* 9 \W */ - OP_WORDCHAR, /* 10 \w */ - OP_ANY, /* 11 Match any character */ - OP_ANYBYTE, /* 12 Match any byte (\C); different to OP_ANY for UTF-8 */ - OP_NOTPROP, /* 13 \P (not Unicode property) */ - OP_PROP, /* 14 \p (Unicode property) */ - OP_ANYNL, /* 15 \R (any newline sequence) */ - OP_EXTUNI, /* 16 \X (extended Unicode sequence */ - OP_EODN, /* 17 End of data or \n at end of data: \Z. */ - OP_EOD, /* 18 End of data: \z */ - - OP_OPT, /* 19 Set runtime options */ - OP_CIRC, /* 20 Start of line - varies with multiline switch */ - OP_DOLL, /* 21 End of line - varies with multiline switch */ - OP_CHAR, /* 22 Match one character, casefully */ - OP_CHARNC, /* 23 Match one character, caselessly */ - OP_NOT, /* 24 Match one character, not the following one */ - - OP_STAR, /* 25 The maximizing and minimizing versions of */ - OP_MINSTAR, /* 26 these six opcodes must come in pairs, with */ - OP_PLUS, /* 27 the minimizing one second. */ - OP_MINPLUS, /* 28 This first set applies to single characters.*/ - OP_QUERY, /* 29 */ - OP_MINQUERY, /* 30 */ - - OP_UPTO, /* 31 From 0 to n matches */ - OP_MINUPTO, /* 32 */ - OP_EXACT, /* 33 Exactly n matches */ - - OP_POSSTAR, /* 34 Possessified star */ - OP_POSPLUS, /* 35 Possessified plus */ - OP_POSQUERY, /* 36 Posesssified query */ - OP_POSUPTO, /* 37 Possessified upto */ - - OP_NOTSTAR, /* 38 The maximizing and minimizing versions of */ - OP_NOTMINSTAR, /* 39 these six opcodes must come in pairs, with */ - OP_NOTPLUS, /* 40 the minimizing one second. They must be in */ - OP_NOTMINPLUS, /* 41 exactly the same order as those above. */ - OP_NOTQUERY, /* 42 This set applies to "not" single characters. */ - OP_NOTMINQUERY, /* 43 */ - - OP_NOTUPTO, /* 44 From 0 to n matches */ - OP_NOTMINUPTO, /* 45 */ - OP_NOTEXACT, /* 46 Exactly n matches */ - - OP_NOTPOSSTAR, /* 47 Possessified versions */ - OP_NOTPOSPLUS, /* 48 */ - OP_NOTPOSQUERY, /* 49 */ - OP_NOTPOSUPTO, /* 50 */ - - OP_TYPESTAR, /* 51 The maximizing and minimizing versions of */ - OP_TYPEMINSTAR, /* 52 these six opcodes must come in pairs, with */ - OP_TYPEPLUS, /* 53 the minimizing one second. These codes must */ - OP_TYPEMINPLUS, /* 54 be in exactly the same order as those above. */ - OP_TYPEQUERY, /* 55 This set applies to character types such as \d */ - OP_TYPEMINQUERY, /* 56 */ - - OP_TYPEUPTO, /* 57 From 0 to n matches */ - OP_TYPEMINUPTO, /* 58 */ - OP_TYPEEXACT, /* 59 Exactly n matches */ - - OP_TYPEPOSSTAR, /* 60 Possessified versions */ - OP_TYPEPOSPLUS, /* 61 */ - OP_TYPEPOSQUERY, /* 62 */ - OP_TYPEPOSUPTO, /* 63 */ - - OP_CRSTAR, /* 64 The maximizing and minimizing versions of */ - OP_CRMINSTAR, /* 65 all these opcodes must come in pairs, with */ - OP_CRPLUS, /* 66 the minimizing one second. These codes must */ - OP_CRMINPLUS, /* 67 be in exactly the same order as those above. */ - OP_CRQUERY, /* 68 These are for character classes and back refs */ - OP_CRMINQUERY, /* 69 */ - OP_CRRANGE, /* 70 These are different to the three sets above. */ - OP_CRMINRANGE, /* 71 */ - - OP_CLASS, /* 72 Match a character class, chars < 256 only */ - OP_NCLASS, /* 73 Same, but the bitmap was created from a negative + 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 */ + OP_ANYBYTE, /* 13 Match any byte (\C); different to OP_ANY for UTF-8 */ + OP_NOTPROP, /* 14 \P (not Unicode property) */ + OP_PROP, /* 15 \p (Unicode property) */ + OP_ANYNL, /* 16 \R (any newline sequence) */ + OP_NOT_HSPACE, /* 17 \H (not horizontal whitespace) */ + OP_HSPACE, /* 18 \h (horizontal whitespace) */ + OP_NOT_VSPACE, /* 19 \V (not vertical whitespace) */ + OP_VSPACE, /* 20 \v (vertical whitespace) */ + OP_EXTUNI, /* 21 \X (extended Unicode sequence */ + OP_EODN, /* 22 End of data or \n at end of data: \Z. */ + OP_EOD, /* 23 End of data: \z */ + + OP_OPT, /* 24 Set runtime options */ + OP_CIRC, /* 25 Start of line - varies with multiline switch */ + OP_DOLL, /* 26 End of line - varies with multiline switch */ + OP_CHAR, /* 27 Match one character, casefully */ + OP_CHARNC, /* 28 Match one character, caselessly */ + OP_NOT, /* 29 Match one character, not the following one */ + + OP_STAR, /* 30 The maximizing and minimizing versions of */ + OP_MINSTAR, /* 31 these six opcodes must come in pairs, with */ + OP_PLUS, /* 32 the minimizing one second. */ + OP_MINPLUS, /* 33 This first set applies to single characters.*/ + OP_QUERY, /* 34 */ + OP_MINQUERY, /* 35 */ + + OP_UPTO, /* 36 From 0 to n matches */ + OP_MINUPTO, /* 37 */ + OP_EXACT, /* 38 Exactly n matches */ + + OP_POSSTAR, /* 39 Possessified star */ + OP_POSPLUS, /* 40 Possessified plus */ + OP_POSQUERY, /* 41 Posesssified query */ + OP_POSUPTO, /* 42 Possessified upto */ + + OP_NOTSTAR, /* 43 The maximizing and minimizing versions of */ + OP_NOTMINSTAR, /* 44 these six opcodes must come in pairs, with */ + OP_NOTPLUS, /* 45 the minimizing one second. They must be in */ + OP_NOTMINPLUS, /* 46 exactly the same order as those above. */ + OP_NOTQUERY, /* 47 This set applies to "not" single characters. */ + OP_NOTMINQUERY, /* 48 */ + + OP_NOTUPTO, /* 49 From 0 to n matches */ + OP_NOTMINUPTO, /* 50 */ + OP_NOTEXACT, /* 51 Exactly n matches */ + + OP_NOTPOSSTAR, /* 52 Possessified versions */ + OP_NOTPOSPLUS, /* 53 */ + OP_NOTPOSQUERY, /* 54 */ + OP_NOTPOSUPTO, /* 55 */ + + OP_TYPESTAR, /* 56 The maximizing and minimizing versions of */ + OP_TYPEMINSTAR, /* 57 these six opcodes must come in pairs, with */ + OP_TYPEPLUS, /* 58 the minimizing one second. These codes must */ + OP_TYPEMINPLUS, /* 59 be in exactly the same order as those above. */ + OP_TYPEQUERY, /* 60 This set applies to character types such as \d */ + OP_TYPEMINQUERY, /* 61 */ + + OP_TYPEUPTO, /* 62 From 0 to n matches */ + OP_TYPEMINUPTO, /* 63 */ + OP_TYPEEXACT, /* 64 Exactly n matches */ + + OP_TYPEPOSSTAR, /* 65 Possessified versions */ + OP_TYPEPOSPLUS, /* 66 */ + OP_TYPEPOSQUERY, /* 67 */ + OP_TYPEPOSUPTO, /* 68 */ + + OP_CRSTAR, /* 69 The maximizing and minimizing versions of */ + OP_CRMINSTAR, /* 70 all these opcodes must come in pairs, with */ + OP_CRPLUS, /* 71 the minimizing one second. These codes must */ + OP_CRMINPLUS, /* 72 be in exactly the same order as those above. */ + OP_CRQUERY, /* 73 These are for character classes and back refs */ + OP_CRMINQUERY, /* 74 */ + OP_CRRANGE, /* 75 These are different to the three sets above. */ + OP_CRMINRANGE, /* 76 */ + + OP_CLASS, /* 77 Match a character class, chars < 256 only */ + OP_NCLASS, /* 78 Same, but the bitmap was created from a negative class - the difference is relevant only when a UTF-8 character > 255 is encountered. */ - OP_XCLASS, /* 74 Extended class for handling UTF-8 chars within the + OP_XCLASS, /* 79 Extended class for handling UTF-8 chars within the class. This does both positive and negative. */ - OP_REF, /* 75 Match a back reference */ - OP_RECURSE, /* 76 Match a numbered subpattern (possibly recursive) */ - OP_CALLOUT, /* 77 Call out to external function if provided */ + OP_REF, /* 80 Match a back reference */ + OP_RECURSE, /* 81 Match a numbered subpattern (possibly recursive) */ + OP_CALLOUT, /* 82 Call out to external function if provided */ - OP_ALT, /* 78 Start of alternation */ - OP_KET, /* 79 End of group that doesn't have an unbounded repeat */ - OP_KETRMAX, /* 80 These two must remain together and in this */ - OP_KETRMIN, /* 81 order. They are for groups the repeat for ever. */ + OP_ALT, /* 83 Start of alternation */ + OP_KET, /* 84 End of group that doesn't have an unbounded repeat */ + OP_KETRMAX, /* 85 These two must remain together and in this */ + OP_KETRMIN, /* 86 order. They are for groups the repeat for ever. */ /* The assertions must come before BRA, CBRA, ONCE, and COND.*/ - OP_ASSERT, /* 82 Positive lookahead */ - OP_ASSERT_NOT, /* 83 Negative lookahead */ - OP_ASSERTBACK, /* 84 Positive lookbehind */ - OP_ASSERTBACK_NOT, /* 85 Negative lookbehind */ - OP_REVERSE, /* 86 Move pointer back - used in lookbehind assertions */ + OP_ASSERT, /* 87 Positive lookahead */ + OP_ASSERT_NOT, /* 88 Negative lookahead */ + OP_ASSERTBACK, /* 89 Positive lookbehind */ + OP_ASSERTBACK_NOT, /* 90 Negative lookbehind */ + OP_REVERSE, /* 91 Move pointer back - used in lookbehind assertions */ /* ONCE, BRA, CBRA, and COND must come after the assertions, with ONCE first, as there's a test for >= ONCE for a subpattern that isn't an assertion. */ - OP_ONCE, /* 87 Atomic group */ - OP_BRA, /* 88 Start of non-capturing bracket */ - OP_CBRA, /* 89 Start of capturing bracket */ - OP_COND, /* 90 Conditional group */ + OP_ONCE, /* 92 Atomic group */ + OP_BRA, /* 83 Start of non-capturing bracket */ + OP_CBRA, /* 94 Start of capturing bracket */ + OP_COND, /* 95 Conditional group */ /* These three must follow the previous three, in the same order. There's a check for >= SBRA to distinguish the two sets. */ - OP_SBRA, /* 91 Start of non-capturing bracket, check empty */ - OP_SCBRA, /* 92 Start of capturing bracket, check empty */ - OP_SCOND, /* 93 Conditional group, check empty */ + OP_SBRA, /* 96 Start of non-capturing bracket, check empty */ + OP_SCBRA, /* 97 Start of capturing bracket, check empty */ + OP_SCOND, /* 98 Conditional group, check empty */ - OP_CREF, /* 94 Used to hold a capture number as condition */ - OP_RREF, /* 95 Used to hold a recursion number as condition */ - OP_DEF, /* 96 The DEFINE condition */ + OP_CREF, /* 99 Used to hold a capture number as condition */ + OP_RREF, /* 100 Used to hold a recursion number as condition */ + OP_DEF, /* 101 The DEFINE condition */ - OP_BRAZERO, /* 97 These two must remain together and in this */ - OP_BRAMINZERO /* 98 order. */ + OP_BRAZERO, /* 102 These two must remain together and in this */ + OP_BRAMINZERO /* 103 order. */ }; @@ -701,10 +770,10 @@ enum { for debugging. The macro is referenced only in pcre_printint.c. */ #define OP_NAME_LIST \ - "End", "\\A", "\\G", "\\B", "\\b", "\\D", "\\d", \ + "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d", \ "\\S", "\\s", "\\W", "\\w", "Any", "Anybyte", \ - "notprop", "prop", "anynl", "extuni", \ - "\\Z", "\\z", \ + "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v", \ + "extuni", "\\Z", "\\z", \ "Opt", "^", "$", "char", "charnc", "not", \ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ "*+","++", "?+", "{", \ @@ -731,9 +800,11 @@ 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, 1, 1, 1, 1, 1, /* \A, \G, \B, \B, \D, \d, \S, \s, \W, \w */ \ + 1, 1, 1, 1, 1, /* \A, \G, \K, \B, \b */ \ + 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ \ 1, 1, /* Any, Anybyte */ \ - 3, 3, 1, 1, /* NOTPROP, PROP, EXTUNI, ANYNL */ \ + 3, 3, 1, /* NOTPROP, PROP, EXTUNI */ \ + 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ \ 1, 1, 2, 1, 1, /* \Z, \z, Opt, ^, $ */ \ 2, /* Char - the minimum length */ \ 2, /* Charnc - the minimum length */ \ @@ -793,7 +864,7 @@ enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, 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 }; + ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58 }; /* 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 @@ -882,21 +953,11 @@ typedef struct recursion_info { struct recursion_info *prevrec; /* Previous recursion record (or NULL) */ int group_num; /* Number of group that was called */ const uschar *after_call; /* "Return value": points after the call in the expr */ - USPTR save_start; /* Old value of md->start_match */ + USPTR save_start; /* Old value of mstart */ int *offset_save; /* Pointer to start of saved offsets */ int saved_max; /* Number of saved offsets */ } recursion_info; -/* When compiling in a mode that doesn't use recursive calls to match(), -a structure is used to remember local variables on the heap. It is defined in -pcre_exec.c, close to the match() function, so that it is easy to keep it in -step with any changes of local variable. However, the pointer to the current -frame must be saved in some "static" place over a longjmp(). We declare the -structure here so that we can put a pointer in the match_data structure. NOTE: -This isn't used for a "normal" compilation of pcre. */ - -struct heapframe; - /* 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. */ @@ -933,7 +994,7 @@ typedef struct match_data { const uschar *start_code; /* For use when recursing */ USPTR start_subject; /* Start of the subject string */ USPTR end_subject; /* End of the subject string */ - USPTR start_match; /* Start of this match attempt */ + USPTR start_match_ptr; /* Start of matched string */ USPTR end_match_ptr; /* Subject position at end match */ int end_offset_top; /* Highwater mark at end of match */ int capture_last; /* Most recent capture number */ @@ -942,7 +1003,6 @@ typedef struct match_data { int eptrn; /* Next free eptrblock */ recursion_info *recursive; /* Linked list of recursion data */ void *callout_data; /* To pass back to callouts */ - struct heapframe *thisframe; /* Used only when compiling for no recursion */ } match_data; /* A similar structure is used for the same purpose by the DFA matching @@ -1028,16 +1088,16 @@ extern const uschar _pcre_OP_lengths[]; one of the exported public functions. They have to be "external" in the C sense, but are not part of the PCRE public API. */ -extern BOOL _pcre_is_newline(const uschar *, const uschar *, int *, - BOOL); +extern BOOL _pcre_is_newline(const uschar *, int, const uschar *, + int *, BOOL); extern int _pcre_ord2utf8(int, uschar *); extern real_pcre *_pcre_try_flipped(const real_pcre *, real_pcre *, const pcre_study_data *, pcre_study_data *); extern int _pcre_ucp_findprop(const unsigned int, int *, int *); extern unsigned int _pcre_ucp_othercase(const unsigned int); extern int _pcre_valid_utf8(const uschar *, int); -extern BOOL _pcre_was_newline(const uschar *, const uschar *, int *, - BOOL); +extern BOOL _pcre_was_newline(const uschar *, int, const uschar *, + int *, BOOL); extern BOOL _pcre_xclass(int, const uschar *); #endif diff --git a/src/src/pcre/pcre_maketables.c b/src/src/pcre/pcre_maketables.c index b78019efc..6209c25dc 100644 --- a/src/src/pcre/pcre_maketables.c +++ b/src/src/pcre/pcre_maketables.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_maketables.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_maketables.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without diff --git a/src/src/pcre/pcre_newline.c b/src/src/pcre/pcre_newline.c index 26cf0fe1f..bf0ade5ae 100644 --- a/src/src/pcre/pcre_newline.c +++ b/src/src/pcre/pcre_newline.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_newline.c,v 1.1 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_newline.c,v 1.2 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -44,9 +44,8 @@ POSSIBILITY OF SUCH DAMAGE. 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, and NLTYPE_ALL, -so for now the type isn't passed into the functions. It can easily be added -later if required. The full list of Unicode newline characters is taken from +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/. */ @@ -63,6 +62,7 @@ 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 utf8 TRUE if in utf8 mode @@ -71,12 +71,23 @@ Returns: TRUE or FALSE */ BOOL -_pcre_is_newline(const uschar *ptr, const uschar *endptr, int *lenptr, - BOOL utf8) +_pcre_is_newline(const uschar *ptr, int type, const uschar *endptr, + int *lenptr, BOOL utf8) { int c; if (utf8) { GETCHAR(c, ptr); } else c = *ptr; -switch(c) + +if (type == NLTYPE_ANYCRLF) switch(c) + { + case 0x000a: *lenptr = 1; return TRUE; /* LF */ + case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1; + return TRUE; /* CR */ + default: return FALSE; + } + +/* NLTYPE_ANY */ + +else switch(c) { case 0x000a: /* LF */ case 0x000b: /* VT */ @@ -101,6 +112,7 @@ 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 utf8 TRUE if in utf8 mode @@ -109,8 +121,8 @@ Returns: TRUE or FALSE */ BOOL -_pcre_was_newline(const uschar *ptr, const uschar *startptr, int *lenptr, - BOOL utf8) +_pcre_was_newline(const uschar *ptr, int type, const uschar *startptr, + int *lenptr, BOOL utf8) { int c; ptr--; @@ -120,7 +132,16 @@ if (utf8) GETCHAR(c, ptr); } else c = *ptr; -switch(c) + +if (type == NLTYPE_ANYCRLF) switch(c) + { + case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1; + return TRUE; /* LF */ + case 0x000d: *lenptr = 1; return TRUE; /* CR */ + default: return FALSE; + } + +else switch(c) { case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1; return TRUE; /* LF */ diff --git a/src/src/pcre/pcre_printint.src b/src/src/pcre/pcre_printint.src index e5407f81b..7e2837b72 100644 --- a/src/src/pcre/pcre_printint.src +++ b/src/src/pcre/pcre_printint.src @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_printint.src,v 1.2 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_printint.src,v 1.3 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2005 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -73,6 +73,12 @@ print_char(FILE *f, uschar *ptr, BOOL utf8) { int c = *ptr; +#ifndef SUPPORT_UTF8 +utf8 = utf8; /* Avoid compiler warning */ +if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c); +return 0; + +#else if (!utf8 || (c & 0xc0) != 0xc0) { if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c); @@ -104,6 +110,7 @@ else if (c < 128) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%x}", c); return a; } +#endif } @@ -136,10 +143,13 @@ return (ptype == pvalue)? "??" : "??"; *************************************************/ /* Make this function work for a regex with integers either byte order. -However, we assume that what we are passed is a compiled regex. */ +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. */ static void -pcre_printint(pcre *external_re, FILE *f) +pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths) { real_pcre *re = (real_pcre *)external_re; uschar *codestart, *code; @@ -170,7 +180,10 @@ for(;;) int c; int extra = 0; - fprintf(f, "%3d ", (int)(code - codestart)); + if (print_lengths) + fprintf(f, "%3d ", (int)(code - codestart)); + else + fprintf(f, " "); switch(*code) { @@ -207,8 +220,9 @@ for(;;) case OP_CBRA: case OP_SCBRA: - fprintf(f, "%3d %s %d", GET(code, 1), OP_names[*code], - GET2(code, 1+LINK_SIZE)); + if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); + else fprintf(f, " "); + fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE)); break; case OP_BRA: @@ -225,7 +239,9 @@ for(;;) case OP_COND: case OP_SCOND: case OP_REVERSE: - fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]); + if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); + else fprintf(f, " "); + fprintf(f, "%s", OP_names[*code]); break; case OP_CREF: @@ -341,7 +357,9 @@ for(;;) break; case OP_RECURSE: - fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]); + if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); + else fprintf(f, " "); + fprintf(f, "%s", OP_names[*code]); break; case OP_REF: diff --git a/src/src/pcre/pcre_study.c b/src/src/pcre/pcre_study.c index ae312f272..8858f7f40 100644 --- a/src/src/pcre/pcre_study.c +++ b/src/src/pcre/pcre_study.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_study.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_study.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -396,11 +396,13 @@ do character with a value > 255. */ case OP_NCLASS: +#ifdef SUPPORT_UTF8 if (utf8) { start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */ memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */ } +#endif /* Fall through */ case OP_CLASS: @@ -413,6 +415,7 @@ do value is > 127. In fact, there are only two possible starting bytes for characters in the range 128 - 255. */ +#ifdef SUPPORT_UTF8 if (utf8) { for (c = 0; c < 16; c++) start_bits[c] |= tcode[c]; @@ -430,6 +433,7 @@ do /* In non-UTF-8 mode, the two bit maps are completely compatible. */ else +#endif { for (c = 0; c < 32; c++) start_bits[c] |= tcode[c]; } @@ -489,7 +493,7 @@ Returns: pointer to a pcre_extra block, with study_data filled in and the NULL on error or if no optimization possible */ -PCRE_DATA_SCOPE pcre_extra * +PCRE_EXP_DEFN pcre_extra * pcre_study(const pcre *external_re, int options, const char **errorptr) { uschar start_bits[32]; diff --git a/src/src/pcre/pcre_tables.c b/src/src/pcre/pcre_tables.c index 1f4649f76..1c2f1cd06 100644 --- a/src/src/pcre/pcre_tables.c +++ b/src/src/pcre/pcre_tables.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_tables.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_tables.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -63,6 +63,8 @@ const uschar _pcre_OP_lengths[] = { OP_LENGTHS }; /* These are the breakpoints for different numbers of bytes in a UTF-8 character. */ +#ifdef SUPPORT_UTF8 + const int _pcre_utf8_table1[] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; @@ -196,4 +198,6 @@ const ucp_type_table _pcre_utt[] = { const int _pcre_utt_size = sizeof(_pcre_utt)/sizeof(ucp_type_table); +#endif /* SUPPORT_UTF8 */ + /* End of pcre_tables.c */ diff --git a/src/src/pcre/pcre_try_flipped.c b/src/src/pcre/pcre_try_flipped.c index d0b652037..1c08eb6fa 100644 --- a/src/src/pcre/pcre_try_flipped.c +++ b/src/src/pcre/pcre_try_flipped.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_try_flipped.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_try_flipped.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without diff --git a/src/src/pcre/pcre_version.c b/src/src/pcre/pcre_version.c index 1a30fe014..d4f8e2a8a 100644 --- a/src/src/pcre/pcre_version.c +++ b/src/src/pcre/pcre_version.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcre_version.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcre_version.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Perl-Compatible Regular Expressions * @@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2006 University of Cambridge + Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -77,7 +77,7 @@ 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. */ -PCRE_DATA_SCOPE const char * +PCRE_EXP_DEFN const char * pcre_version(void) { return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)? diff --git a/src/src/pcre/pcretest.c b/src/src/pcre/pcretest.c index a572a9dfc..98d10445e 100644 --- a/src/src/pcre/pcretest.c +++ b/src/src/pcre/pcretest.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/pcretest.c,v 1.6 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/pcretest.c,v 1.7 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * PCRE testing program * @@ -69,13 +69,16 @@ input mode under Windows. */ #endif -#define PCRE_SPY /* For Win32 build, import data, not export */ +/* 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. -/* We 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" /* We need access to the data tables that PCRE uses. So as not to have to keep @@ -116,10 +119,17 @@ Makefile. */ #include "pcreposix.h" #endif -/* It is also possible, for the benefit of the version imported into Exim, to -build pcretest without support for UTF8 (define NOUTF8), without the interface -to the DFA matcher (NODFA), and without the doublecheck of the old "info" -function (define NOINFOCHECK). */ +/* It is also possible, for the benefit of the version currently imported into +Exim, to build pcretest without support for UTF8 (define NOUTF8), without the +interface to the DFA matcher (NODFA), and without the doublecheck of the old +"info" function (define NOINFOCHECK). In fact, we automatically cut out the +UTF8 support if PCRE is built without it. */ + +#ifndef SUPPORT_UTF8 +#ifndef NOUTF8 +#define NOUTF8 +#endif +#endif /* Other parameters */ @@ -655,7 +665,8 @@ return count; *************************************************/ /* This is used both at compile and run-time to check for <xxx> escapes, where -xxx is LF, CR, CRLF, or ANY. Print a message and return 0 if there is no match. +xxx is LF, CR, CRLF, ANYCRLF, or ANY. Print a message and return 0 if there is +no match. Arguments: p points after the leading '<' @@ -670,6 +681,7 @@ check_newline(uschar *p, FILE *f) if (strncmp((char *)p, "cr>", 3) == 0) return PCRE_NEWLINE_CR; if (strncmp((char *)p, "lf>", 3) == 0) return PCRE_NEWLINE_LF; if (strncmp((char *)p, "crlf>", 5) == 0) return PCRE_NEWLINE_CRLF; +if (strncmp((char *)p, "anycrlf>", 8) == 0) return PCRE_NEWLINE_ANYCRLF; if (strncmp((char *)p, "any>", 4) == 0) return PCRE_NEWLINE_ANY; fprintf(f, "Unknown newline type at: <%s\n", p); return 0; @@ -842,6 +854,7 @@ while (argc > 1 && argv[op][0] == '-') (void)pcre_config(PCRE_CONFIG_NEWLINE, &rc); printf(" Newline sequence is %s\n", (rc == '\r')? "CR" : (rc == '\n')? "LF" : (rc == ('\r'<<8 | '\n'))? "CRLF" : + (rc == -2)? "ANYCRLF" : (rc == -1)? "ANY" : "???"); (void)pcre_config(PCRE_CONFIG_LINK_SIZE, &rc); printf(" Internal link size = %d\n", rc); @@ -853,7 +866,7 @@ while (argc > 1 && argv[op][0] == '-') printf(" Default recursion depth limit = %d\n", rc); (void)pcre_config(PCRE_CONFIG_STACKRECURSE, &rc); printf(" Match recursion uses %s\n", rc? "stack" : "heap"); - exit(0); + goto EXIT; } else if (strcmp(argv[op], "-help") == 0 || strcmp(argv[op], "--help") == 0) @@ -879,7 +892,7 @@ offsets = (int *)malloc(size_offsets_max * sizeof(int)); if (offsets == NULL) { printf("** Failed to get %d bytes of memory for offsets vector\n", - size_offsets_max * sizeof(int)); + (int)(size_offsets_max * sizeof(int))); yield = 1; goto EXIT; } @@ -939,6 +952,7 @@ while (!done) size_t size, regex_gotten_store; int do_study = 0; int do_debug = debug; + int debug_lengths = 1; int do_G = 0; int do_g = 0; int do_showinfo = showinfo; @@ -1129,6 +1143,7 @@ while (!done) case 'S': do_study = 1; break; case 'U': options |= PCRE_UNGREEDY; break; case 'X': options |= PCRE_EXTRA; break; + case 'Z': debug_lengths = 0; break; case '8': options |= PCRE_UTF8; use_utf8 = 1; break; case '?': options |= PCRE_NO_UTF8_CHECK; break; @@ -1330,7 +1345,7 @@ while (!done) if (do_debug) { fprintf(outfile, "------------------------------------------------------------------\n"); - pcre_printint(re, outfile); + pcre_printint(re, outfile, debug_lengths); } if (do_showinfo) @@ -1339,7 +1354,7 @@ while (!done) #if !defined NOINFOCHECK int old_first_char, old_options, old_count; #endif - int count, backrefmax, first_char, need_char; + int count, backrefmax, first_char, need_char, okpartial, jchanged; int nameentrysize, namecount; const uschar *nametable; @@ -1352,6 +1367,8 @@ while (!done) 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); #if !defined NOINFOCHECK old_count = pcre_info(re, &old_options, &old_first_char); @@ -1393,17 +1410,10 @@ while (!done) } } - /* The NOPARTIAL bit is a private bit in the options, so we have - to fish it out via out back door */ + if (!okpartial) fprintf(outfile, "Partial matching not supported\n"); all_options = ((real_pcre *)re)->options; - if (do_flip) - { - all_options = byteflip(all_options, sizeof(all_options)); - } - - if ((all_options & PCRE_NOPARTIAL) != 0) - fprintf(outfile, "Partial matching not supported\n"); + if (do_flip) all_options = byteflip(all_options, sizeof(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\n", @@ -1421,6 +1431,8 @@ while (!done) ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf8_check" : "", ((get_options & PCRE_DUPNAMES) != 0)? " dupnames" : ""); + if (jchanged) fprintf(outfile, "Duplicate name status changes\n"); + switch (get_options & PCRE_NEWLINE_BITS) { case PCRE_NEWLINE_CR: @@ -1435,6 +1447,10 @@ while (!done) 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; @@ -1584,7 +1600,7 @@ while (!done) for (;;) { uschar *q; - uschar *bptr = dbuffer; + uschar *bptr; int *use_offsets = offsets; int use_size_offsets = size_offsets; int callout_data = 0; @@ -1640,7 +1656,7 @@ while (!done) p = buffer; while (isspace(*p)) p++; - q = dbuffer; + bptr = q = dbuffer; while ((c = *p++) != 0) { int i = 0; @@ -1835,7 +1851,7 @@ while (!done) if (offsets == NULL) { printf("** Failed to get %d bytes of memory for offsets vector\n", - size_offsets_max * sizeof(int)); + (int)(size_offsets_max * sizeof(int))); yield = 1; goto EXIT; } @@ -2204,19 +2220,44 @@ while (!done) } /* 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. In the case of UTF-8 - matching, the advance must be one character, not one byte. Fudge the - offset values to achieve this. We won't be at the end of the string - - that was checked before setting g_notempty. */ + 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 option is "any" 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. + + 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 *)re)->options; use_offsets[0] = start_offset; - if (use_utf8) + if ((obits & PCRE_NEWLINE_BITS) == 0) + { + int d; + (void)pcre_config(PCRE_CONFIG_NEWLINE, &d); + obits = (d == '\r')? PCRE_NEWLINE_CR : + (d == '\n')? PCRE_NEWLINE_LF : + (d == ('\r'<<8 | '\n'))? 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_ANYCRLF) + && + start_offset < len - 1 && + bptr[start_offset] == '\r' && + bptr[start_offset+1] == '\n') + onechar++; + else if (use_utf8) { while (start_offset + onechar < len) { @@ -2251,6 +2292,7 @@ while (!done) character. */ g_notempty = 0; + if (use_offsets[0] == use_offsets[1]) { if (use_offsets[0] == len) break; diff --git a/src/src/pcre/ucp.h b/src/src/pcre/ucp.h index 5dcd10520..288854e67 100644 --- a/src/src/pcre/ucp.h +++ b/src/src/pcre/ucp.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/pcre/ucp.h,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/pcre/ucp.h,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */ /************************************************* * Unicode Property Table handler * |