[PENNMUSH-ANNOUNCE] 1.7.6-patch10
dunemush at tala.mede.uic.edu
dunemush at tala.mede.uic.edu
Thu May 22 14:36:53 CDT 2003
This is patch10 to PennMUSH 1.7.6. After applying this patch, you will
have version 1.7.6p10
To apply this patch, save it to a file in your top-level MUSH directory,
and do the following:
patch -p1 < 1.7.6-patch10
make install
If you use GNU patch 2.2, you probably want the above to be 'patch -b -p1',
not just 'patch -p1'.
Unix (or cygwin) users need not worry about failed hunks in src/switchinc.c,
hdrs/switches.h, hdrs/cmds.h, or hdrs/funs.h. These files are automatically
rebuilt on compile. On the off chance they appear not to be, simply
rm them and re-run make.
Then @shutdown and restart your MUSH.
- Alan/Javelin
In this patch:
Minor changes:
* PCRE (the regex matching engine we use) is updated to version 4.2. [SW]
* @mail/file now unclears the cleared bit when filing @mail.
Suggested by Philip Mak.
Fixes:
* @edit is better with editing ansi. Reported by Trispis at M*U*S*H. [SW]
* Help file cleanup. [SW]
* @warnings about missing FAILURE messages were not correctly
checked, causing false positives. Reported by Cheetah.
* Page message no longer ends in a period. Suggested by Time at M*U*S*H.
* Help fixes by Intrevis at M*U*S*H.
* BASE_ROOM can't be destroyed any more. Suggested by Philip Mak.
Prereq: 1.7.6p9
*** 1_7_6.144/Patchlevel Wed, 09 Apr 2003 13:49:37 -0500 dunemush (pennmush/5_Patchlevel 1.17.1.11.1.1.1.9 600)
--- 1_7_6.153(w)/Patchlevel Tue, 13 May 2003 12:47:38 -0500 dunemush (pennmush/5_Patchlevel 1.17.1.11.1.1.1.9 600)
***************
*** 1,2 ****
Do not edit this file. It is maintained by the official PennMUSH patches.
! This is PennMUSH 1.7.6p9
--- 1,2 ----
Do not edit this file. It is maintained by the official PennMUSH patches.
! This is PennMUSH 1.7.6p10
*** 1_7_6.144/CHANGES.176 Wed, 09 Apr 2003 13:49:37 -0500 dunemush (pennmush/g/17_CHANGES 1.10.1.6.1.2.1.2.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.9.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1 600)
--- 1_7_6.153(w)/CHANGES.176 Tue, 13 May 2003 12:28:00 -0500 dunemush (pennmush/g/17_CHANGES 1.10.1.6.1.2.1.2.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.9.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1 600)
***************
*** 18,23 ****
--- 18,39 ----
==========================================================================
+ Version 1.7.6 patchlevel 10 May 13, 2003
+
+ Minor changes:
+ * PCRE (the regex matching engine we use) is updated to version 4.2. [SW]
+ * @mail/file now unclears the cleared bit when filing @mail.
+ Suggested by Philip Mak.
+ Fixes:
+ * @edit is better with editing ansi. Reported by Trispis at M*U*S*H. [SW]
+ * Help file cleanup. [SW]
+ * @warnings about missing FAILURE messages were not correctly
+ checked, causing false positives. Reported by Cheetah.
+ * Page message no longer ends in a period. Suggested by Time at M*U*S*H.
+ * Help fixes by Intrevis at M*U*S*H.
+ * BASE_ROOM can't be destroyed any more. Suggested by Philip Mak.
+
+
Version 1.7.6 patchlevel 9 April 9, 2003
Fixes:
***************
*** 30,36 ****
* Configure test for /dev/urandom from 1.7.5 got left out by mistake.
* Critical overflow bug in command argument parsing fixed.
-
Version 1.7.6 patchlevel 8 March 21, 2003
Minor changes:
--- 46,51 ----
*** 1_7_6.144/game/txt/hlp/pennvOLD.hlp Sat, 29 Mar 2003 21:47:33 -0600 dunemush (pennmush/g/30_pennvOLD.h 1.1.1.1 660)
--- 1_7_6.153(w)/game/txt/hlp/pennvOLD.hlp Tue, 13 May 2003 12:31:42 -0500 dunemush (pennmush/g/30_pennvOLD.h 1.1.1.1.1.1 660)
***************
*** 4417,4423 ****
For information on a specific patchlevel of one of the versions listed,
type 'help <version>p<patchlevel>'. For example, 'help 1.7.2p3'
! 1.7.6: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
1.7.5: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
1.7.4: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20
--- 4417,4423 ----
For information on a specific patchlevel of one of the versions listed,
type 'help <version>p<patchlevel>'. For example, 'help 1.7.2p3'
! 1.7.6: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
1.7.5: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
1.7.4: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20
*** 1_7_6.144/game/txt/hlp/pennv176.hlp Wed, 09 Apr 2003 13:49:37 -0500 dunemush (pennmush/g/33_pennv176.h 1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1 660)
--- 1_7_6.153(w)/game/txt/hlp/pennv176.hlp Tue, 13 May 2003 12:31:42 -0500 dunemush (pennmush/g/33_pennv176.h 1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1 660)
***************
*** 1,4 ****
! & 1.7.6p9
& changes
This is a list of changes in this patchlevel which are probably of
interest to players. More information about new commands and functions
--- 1,4 ----
! & 1.7.6p10
& changes
This is a list of changes in this patchlevel which are probably of
interest to players. More information about new commands and functions
***************
*** 11,16 ****
--- 11,33 ----
A list of the patchlevels associated with each release can
be read in 'help patchlevels'.
+ Version 1.7.6 patchlevel 10 May 13, 2003
+
+ Minor changes:
+ * PCRE (the regex matching engine we use) is updated to version 4.2. [SW]
+ * @mail/file now unclears the cleared bit when filing @mail.
+ Suggested by Philip Mak.
+ Fixes:
+ * @edit is better with editing ansi. Reported by Trispis at M*U*S*H. [SW]
+ * Help file cleanup. [SW]
+ * @warnings about missing FAILURE messages were not correctly
+ checked, causing false positives. Reported by Cheetah.
+ * Page message no longer ends in a period. Suggested by Time at M*U*S*H.
+ * Help fixes by Intrevis at M*U*S*H.
+ * BASE_ROOM can't be destroyed any more. Suggested by Philip Mak.
+
+
+ & 1.7.6p9
Version 1.7.6 patchlevel 9 April 9, 2003
Fixes:
***************
*** 23,29 ****
* Configure test for /dev/urandom from 1.7.5 got left out by mistake.
* Critical overflow bug in command argument parsing fixed.
-
& 1.7.6p8
Version 1.7.6 patchlevel 8 March 21, 2003
--- 40,45 ----
*** 1_7_6.144/game/txt/hlp/pennfunc.hlp Tue, 18 Mar 2003 15:58:05 -0600 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.8.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.9.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1 600)
--- 1_7_6.153(w)/game/txt/hlp/pennfunc.hlp Wed, 16 Apr 2003 21:48:31 -0500 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.8.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.9.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1 600)
***************
*** 162,168 ****
dec() dist2d() dist3d() div() floordiv()
inc() mod()
! These functions operate only with floating point numbers:
acos() asin() atan() atan2() ceil()
cos() ctu() e() exp() fdiv()
floor() fmod() ln() log() pi()
--- 162,168 ----
dec() dist2d() dist3d() div() floordiv()
inc() mod()
! These functions operate on floating point numbers:
acos() asin() atan() atan2() ceil()
cos() ctu() e() exp() fdiv()
floor() fmod() ln() log() pi()
***************
*** 999,1010 ****
@find. You must control the object in order to perform entrances()
on it.
& EQ()
! [eq(<integer1>,<integer2>)]
! Takes two integers, and returns 1 if they are equal, 0 otherwise.
! Will not work with characters.
! See also: neq(), match()
& ESCAPE()
escape(<string>)
--- 999,1009 ----
@find. You must control the object in order to perform entrances()
on it.
& EQ()
! eq(<number1>,<number2>)
! Takes two numbers, and returns 1 if they are equal, 0 otherwise.
! See also: neq()
& ESCAPE()
escape(<string>)
***************
*** 1061,1074 ****
Returns e to the power of <number>.
& EXTRACT()
! extract(<string>,<first>,<length>[,<delimiter>])
! Extract returns a string of length words, starting with the first
! word. Unlike letters, the first word in a string is number 1,
! instead of 0.
!
! A word is assumed to be defined as a string beginning and ending
! with a space, or a string w/o any interior spaces.
For example:
think extract(This is a test string,3,2)
--- 1060,1069 ----
Returns e to the power of <number>.
& EXTRACT()
! extract(<list>,<first>,<length>[,<delimiter>])
! This function returns <length> elements of a list, counting
! from the <first> element.
For example:
think extract(This is a test string,3,2)
***************
*** 1109,1119 ****
object).
& FIRST()
! first(<string>[,<delimiter>])
! Returns the first word of a string, that is, everything to the left
! of the first space in the string, or the entire string if there are
! no spaces in the string. See REST, LAST.
& FLAGS()
flags(<object>)
flags(<object>/<attribute>)
--- 1104,1114 ----
object).
& FIRST()
! first(<list>[,<delimiter>])
!
! Returns the first element of a list.
! See also: rest(), last()
& FLAGS()
flags(<object>)
flags(<object>/<attribute>)
***************
*** 1240,1253 ****
& FUNCTIONS()
functions()
! Returns a space-separated list of all function names.
& GET()
get(<object>/<attribute>)
! The get function will be replaced by the string stored in the
! attribute of the object. You may get the attributes of objects you
! control, the attributes you control on other objects, and publicly
! accessible attributes.
& GRAB()
& REGRAB()
--- 1235,1247 ----
& FUNCTIONS()
functions()
! Returns a space-separated list of the names of all function.
& GET()
get(<object>/<attribute>)
! The get() function returns the string stored in an object's attribute.
! You may get the attributes of objects you control, the attributes you
! own on other objects, and publicly accessible attributes.
& GRAB()
& REGRAB()
***************
*** 1269,1281 ****
& GRABALL()
& REGRABALL()
& REGRABALLI()
! graball(<string>,<pattern>[,<delim>][,<output seperator])
! regraball(<string>,<regexp>[,<delim>][,<output seperator])
! regraballi(<string>,<regexp>[,<delim>][,<output seperator])
These functions work identically to the grab() and regrab()/regrabi()
functions, save that they return all matches, not just the first: They
! return all words in the list <string> which match <pattern>.
If none match, an empty string is returned.
Examples:
--- 1263,1275 ----
& GRABALL()
& REGRABALL()
& REGRABALLI()
! graball(<list>,<pattern>[,<delim>][,<output seperator])
! regraball(<list>,<regexp>[,<delim>][,<output seperator])
! regraballi(<list>,<regexp>[,<delim>][,<output seperator])
These functions work identically to the grab() and regrab()/regrabi()
functions, save that they return all matches, not just the first: They
! return all words in the <list> which match <pattern>.
If none match, an empty string is returned.
Examples:
***************
*** 1312,1323 ****
This function works exactly like grep or regrep, but is case-insensitive.
See "help grep()" or "help regrep()" for details.
& GT()
! [gt(<num>,<num>)]
Takes two numbers, and returns 1 if and only if the first is greater
than the second, and 0 otherwise.
& GTE()
! [gte(<num>,<num>)]
Takes two numbers, and returns 1 if and only if the first is greater
than or equal to the second, and 0 otherwise.
--- 1306,1317 ----
This function works exactly like grep or regrep, but is case-insensitive.
See "help grep()" or "help regrep()" for details.
& GT()
! gt(<num>,<num>)
Takes two numbers, and returns 1 if and only if the first is greater
than the second, and 0 otherwise.
& GTE()
! gte(<num>,<num>)
Takes two numbers, and returns 1 if and only if the first is greater
than or equal to the second, and 0 otherwise.
***************
*** 1460,1466 ****
& INSERT()
insert(<list>,<position>,<new item>[,<single-character separator>])
! This inserts before the item of <list> at <position> the <new item>.
That means that <new item> then becomes the <position>th element of
<list>. If a separator is not given, a space is assumed. Null items are
counted when determining position, as in 'items()'.
--- 1454,1460 ----
& INSERT()
insert(<list>,<position>,<new item>[,<single-character separator>])
! This inserts <new item> before the item of <list> at <position>.
That means that <new item> then becomes the <position>th element of
<list>. If a separator is not given, a space is assumed. Null items are
counted when determining position, as in 'items()'.
***************
*** 1617,1627 ****
> say [iter(red blue green,iter(fish shoe, [itext(1)]:[itext(0)]))]
You say, "red:fish red:shoe blue:fish blue:shoe green:fish green:shoe"
& LAST()
! last(<string>[,<delimiter>])
! Returns the last word of a string, that is, everything to the right
! of the last space in the string, or the entire string if there are
! no spaces in the string. See FIRST, REST.
& LATTR()
lattr(<object>[/<attribute pattern>])
--- 1611,1621 ----
> say [iter(red blue green,iter(fish shoe, [itext(1)]:[itext(0)]))]
You say, "red:fish red:shoe blue:fish blue:shoe green:fish green:shoe"
& LAST()
! last(<list>[,<delimiter>])
! Returns the last element of a list.
!
! See also: first(), rest()
& LATTR()
lattr(<object>[/<attribute pattern>])
***************
*** 2071,2079 ****
This function works identically to the match() function, save that it
returns all matches, not just the first: It returns the index numbers of
! all elements in the list <string> which match <pattern>. If none match,
! an empty string is returned. The resulting output is delimited by
! <osep>, if given, or else by the delimiter
Examples:
--- 2065,2073 ----
This function works identically to the match() function, save that it
returns all matches, not just the first: It returns the index numbers of
! all elements in <list> which match <pattern>. If none match, an empty
! string is returned. The resulting output is delimited by <osep>, if
! given, or else by the delimiter.
Examples:
***************
*** 2104,2110 ****
has no interior spaces. So ' hello ' would be one word, while
'hello there' would be two. See LISTS
! member() is case-sensitive.
& MERGE()
merge(<string1>, <string2>, <character>)
--- 2098,2105 ----
has no interior spaces. So ' hello ' would be one word, while
'hello there' would be two. See LISTS
! member() is case-sensitive and requires an exact match. For wild
! card patterns, use match().
& MERGE()
merge(<string1>, <string2>, <character>)
***************
*** 2302,2310 ****
object 1 is carrying object 2.
You must control at least one of the objects.
& NEQ()
! [neq(<integer1>,<integer2>)]
! Basically the same as [not(eq(<integer1>,<integer2>))].
See also: eq(), not()
& NEXT()
--- 2297,2305 ----
object 1 is carrying object 2.
You must control at least one of the objects.
& NEQ()
! neq(<num1>,<num2>)
! Basically the same as [not(eq(<num1>,<num2>))].
See also: eq(), not()
& NEXT()
***************
*** 2333,2339 ****
See also: and(), or(), xor(), not()
& NOT()
! [not(<boolean value>)]
Takes a boolean value, and returns its inverse.
I.E. if the input is equivalent to true(1), it returns a 0, and if
--- 2328,2334 ----
See also: and(), or(), xor(), not()
& NOT()
! not(<boolean value>)
Takes a boolean value, and returns its inverse.
I.E. if the input is equivalent to true(1), it returns a 0, and if
***************
*** 2590,2596 ****
A word is defined as a string which contains no interior spaces (or
<delimiter>'s if <delimiter> is used). If the word is not in the
! list, then the list is returned.
To remove all occurrences of a word from a string, consider
using edit().
--- 2585,2591 ----
A word is defined as a string which contains no interior spaces (or
<delimiter>'s if <delimiter> is used). If the word is not in the
! list, then the list is returned. It is case-sensitive.
To remove all occurrences of a word from a string, consider
using edit().
***************
*** 2619,2630 ****
You say, "blue|red|white|yellow"
& REST()
! rest(<string>[,<delimiter>])
! Rest takes a string, returns all the string except the first word,
! that is, everything to the right of the first space, or an empty
! string, or the empty string if there are no spaces in the string.
! See FIRST, LAST.
& REVWORDS()
revwords(<list of words>[,<delimiter>][, <output seperator>])
--- 2614,2624 ----
You say, "blue|red|white|yellow"
& REST()
! rest(<list>[,<delimiter>])
! Returns a list minus its first element.
!
! See also: first(), last()
& REVWORDS()
revwords(<list of words>[,<delimiter>][, <output seperator>])
***************
*** 2874,2882 ****
Performs a rightwards bit-shift on <number>, shifting it <count> times.
This is equivalent to div(<number>,power(2,<count>), but much faster.
& SHUFFLE()
! shuffle(<word1> <word2> <word3> <...wordN>[,<delimiter>][,<osep>])
! This function shuffles the order of words in a list, returning a
random permutation of its elements. "[shuffle(foo bar baz gleep)]"
might evaluate to "baz foo gleep bar".
--- 2868,2876 ----
Performs a rightwards bit-shift on <number>, shifting it <count> times.
This is equivalent to div(<number>,power(2,<count>), but much faster.
& SHUFFLE()
! shuffle(<list>>[,<delimiter>][,<osep>])
! This function shuffles the order of the items of a list, returning a
random permutation of its elements. "[shuffle(foo bar baz gleep)]"
might evaluate to "baz foo gleep bar".
***************
*** 3102,3108 ****
& STRLEN()
strlen(<string>)
! Returns the length of the string in a numerical string.
& STRMATCH()
strmatch(<string>, <pattern>)
--- 3096,3102 ----
& STRLEN()
strlen(<string>)
! Returns the length of the string (The number of characters in it).
& STRMATCH()
strmatch(<string>, <pattern>)
***************
*** 3352,3357 ****
--- 3346,3354 ----
is specified, characters are only trimmed from the right side. If you
specify a trim style, you must also explicitly specify the character
to trim, since the trim style must be the third argument to the function.
+
+ If the tiny_trim_fun config option is "yes", the character and style
+ arguments are reversed.
Examples:
> say [trim( foo bar baz eek )]
***************
*** 3647,3663 ****
This function is equivalent to @wipe. It returns nothing.
& WORDPOS()
! wordpos(<string>, <number>[, <delimiter>])
! Returns the number of the word within <string> where the <number>th
character falls. Characters and words are numbered starting with 1,
and spaces between words are treated as belonging to the word that
follows them. If <number> is not within the string, #-1 is returned.
Example: wordpos(foo bar baz, 5) returns "2"
& WORDS()
! words(<string>[,<delimiter>])
! words() returns the number of words in a string.
& WRAP()
wrap(<string>, <width>[, <first line width>[, <line separator>])
--- 3644,3660 ----
This function is equivalent to @wipe. It returns nothing.
& WORDPOS()
! wordpos(<list>, <number>[, <delimiter>])
! Returns the number of the word within <list> where the <number>th
character falls. Characters and words are numbered starting with 1,
and spaces between words are treated as belonging to the word that
follows them. If <number> is not within the string, #-1 is returned.
Example: wordpos(foo bar baz, 5) returns "2"
& WORDS()
! words(<list>[,<delimiter>])
! words() returns the number of elements in <list>.
& WRAP()
wrap(<string>, <width>[, <first line width>[, <line separator>])
***************
*** 3682,3688 ****
on the use of this function.
& XOR()
! [xor(<boolean value>,<boolean value>)]
Takes two booleans, and returns a 1 if one, and only one of the two
inputs is equivalent to true(1). See BOOLEAN VALUES.
--- 3679,3685 ----
on the use of this function.
& XOR()
! xor(<boolean value>,<boolean value>)
Takes two booleans, and returns a 1 if one, and only one of the two
inputs is equivalent to true(1). See BOOLEAN VALUES.
*** 1_7_6.144/game/txt/hlp/penncmd.hlp Sun, 23 Feb 2003 16:13:43 -0600 dunemush (pennmush/18_penncmd.hl 1.2.1.1.1.47.1.1.1.1.1.3.1.4.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.10.1.1.1.1.1.1.1.1 600)
--- 1_7_6.153(w)/game/txt/hlp/penncmd.hlp Mon, 05 May 2003 20:38:10 -0500 dunemush (pennmush/18_penncmd.hl 1.2.1.1.1.47.1.1.1.1.1.3.1.4.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.10.1.1.1.1.1.1.1.1.1.1 600)
***************
*** 1432,1438 ****
& @hook2
An example of @hook:
! > &top_line #3=pemit(%#, What follows is a the results of a look)
> &bottom_line #3=pemit(%#, You're done looking.)
> @hook/before look=#3, top_line
> @hook/after look=#3, bottom_line
--- 1432,1438 ----
& @hook2
An example of @hook:
! > &top_line #3=pemit(%#, What follows is the results of a look)
> &bottom_line #3=pemit(%#, You're done looking.)
> @hook/before look=#3, top_line
> @hook/after look=#3, bottom_line
*** 1_7_6.144/src/warnings.c Sun, 22 Dec 2002 00:51:08 -0600 dunemush (pennmush/b/25_warnings.c 1.21.1.1 660)
--- 1_7_6.153(w)/src/warnings.c Tue, 13 May 2003 12:48:18 -0500 dunemush (pennmush/b/25_warnings.c 1.21.1.1.1.1 660)
***************
*** 241,247 ****
!atr_get(i, "SUCCESS")))
complain(player, i, "exit-msgs",
T("possibly unlocked exit missing succ/osucc/odrop"));
! if ((lt & W_LOCKED) && !atr_get(i, "FAIL"))
complain(player, i, "exit-msgs",
T("possibly locked exit missing fail"));
}
--- 241,247 ----
!atr_get(i, "SUCCESS")))
complain(player, i, "exit-msgs",
T("possibly unlocked exit missing succ/osucc/odrop"));
! if ((lt & W_LOCKED) && !atr_get(i, "FAILURE"))
complain(player, i, "exit-msgs",
T("possibly locked exit missing fail"));
}
***************
*** 302,308 ****
!atr_get(i, "SUCCESS") || !atr_get(i, "DROP")))
complain(player, i, "thing-msgs",
T("possibly unlocked thing missing succ/osucc/drop/odrop"));
! if ((lt & W_LOCKED) && !atr_get(i, "FAIL"))
complain(player, i, "thing-msgs",
T("possibly locked thing missing fail"));
}
--- 302,308 ----
!atr_get(i, "SUCCESS") || !atr_get(i, "DROP")))
complain(player, i, "thing-msgs",
T("possibly unlocked thing missing succ/osucc/drop/odrop"));
! if ((lt & W_LOCKED) && !atr_get(i, "FAILURE"))
complain(player, i, "thing-msgs",
T("possibly locked thing missing fail"));
}
*** 1_7_6.144/src/switchinc.c Wed, 09 Apr 2003 13:49:37 -0500 dunemush (pennmush/b/32_switchinc. 1.3.1.2.1.6.1.18.1.2.1.2.2.5.1.4.2.4.1.1.1.2.1.5.1.2.1.5.2.1.1.31.3.4.1.5.1.4.1.1.1.1 660)
--- 1_7_6.153(w)/src/switchinc.c Tue, 13 May 2003 12:48:18 -0500 dunemush (pennmush/b/32_switchinc. 1.3.1.2.1.6.1.18.1.2.1.2.2.5.1.4.2.4.1.1.1.2.1.5.1.2.1.5.2.1.1.31.3.4.1.5.1.4.1.1.1.1.1.1 660)
***************
*** 132,136 ****
{"WIZARD", SWITCH_WIZARD},
{"YES", SWITCH_YES},
{"ZONE", SWITCH_ZONE},
! {NULL, 0}
};
--- 132,136 ----
{"WIZARD", SWITCH_WIZARD},
{"YES", SWITCH_YES},
{"ZONE", SWITCH_ZONE},
! {NULL, 0}
};
*** 1_7_6.144/src/speech.c Mon, 03 Mar 2003 21:58:28 -0600 dunemush (pennmush/b/35_speech.c 1.21.1.2.1.3.1.5.1.1.1.7.1.3.1.1.1.8.1.1.1.1.1.1.1.10.1.2.1.13.2.4.1.1.3.1 660)
--- 1_7_6.153(w)/src/speech.c Tue, 13 May 2003 12:48:17 -0500 dunemush (pennmush/b/35_speech.c 1.21.1.2.1.3.1.5.1.1.1.7.1.3.1.1.1.8.1.1.1.1.1.1.1.10.1.2.1.13.2.4.1.1.3.1.1.1 660)
***************
*** 822,828 ****
((gcount > 1) && (!multipage)) ? "(blind) " : "", tbuf2,
Name(player), gap, message);
else
! notify_format(player, T("You paged %s%s with '%s'."),
((gcount > 1) && (!multipage)) ? "(blind) " : "", tbuf2,
message);
--- 822,828 ----
((gcount > 1) && (!multipage)) ? "(blind) " : "", tbuf2,
Name(player), gap, message);
else
! notify_format(player, T("You paged %s%s with '%s'"),
((gcount > 1) && (!multipage)) ? "(blind) " : "", tbuf2,
message);
*** 1_7_6.144/src/set.c Thu, 09 Jan 2003 22:02:38 -0600 dunemush (pennmush/b/38_set.c 1.26.1.5.1.1.2.1.1.1.1.1.1.11.1.1.1.1 660)
--- 1_7_6.153(w)/src/set.c Tue, 13 May 2003 12:48:17 -0500 dunemush (pennmush/b/38_set.c 1.26.1.5.1.1.2.1.1.1.1.1.1.11.1.1.1.1.1.1.1.1 660)
***************
*** 682,690 ****
char tbuf1[BUFFER_LEN], tbuf_ansi[BUFFER_LEN];
char *tbufp, *tbufap;
char **argv = (char **) args;
val = argv[1];
! r = (argv[2]) ? argv[2] : "";
tbufp = tbuf1;
tbufap = tbuf_ansi;
--- 682,693 ----
char tbuf1[BUFFER_LEN], tbuf_ansi[BUFFER_LEN];
char *tbufp, *tbufap;
char **argv = (char **) args;
+ size_t rlen, vlen;
val = argv[1];
! vlen = strlen(val);
! r = argv[2] ? argv[2] : "";
! rlen = strlen(r);
tbufp = tbuf1;
tbufap = tbuf_ansi;
***************
*** 699,705 ****
}
s = (char *) uncompress(a->value); /* warning: pointer to static buffer */
! if (!strcmp(val, "$")) {
/* append */
safe_str(s, tbuf1, &tbufp);
safe_str(r, tbuf1, &tbufp);
--- 702,708 ----
}
s = (char *) uncompress(a->value); /* warning: pointer to static buffer */
! if (vlen == 1 && *val == '$') {
/* append */
safe_str(s, tbuf1, &tbufp);
safe_str(r, tbuf1, &tbufp);
***************
*** 707,713 ****
if (safe_format(tbuf_ansi, &tbufap, "%s%s%s%s", s, ANSI_HILITE, r,
ANSI_NORMAL))
ansi_long_flag = 1;
! } else if (!strcmp(val, "^")) {
/* prepend */
safe_str(r, tbuf1, &tbufp);
safe_str(s, tbuf1, &tbufp);
--- 710,716 ----
if (safe_format(tbuf_ansi, &tbufap, "%s%s%s%s", s, ANSI_HILITE, r,
ANSI_NORMAL))
ansi_long_flag = 1;
! } else if (vlen == 1 && *val == '^') {
/* prepend */
safe_str(r, tbuf1, &tbufp);
safe_str(s, tbuf1, &tbufp);
***************
*** 715,747 ****
if (safe_format(tbuf_ansi, &tbufap, "%s%s%s%s", ANSI_HILITE, r, ANSI_NORMAL,
s))
ansi_long_flag = 1;
} else {
/* find and replace */
! char *p, *start = s;
! Size_t vlen;
int too_long = 0;
! /* This will have problems if val is ever "", but do_gedit makes sure
! * it isn't.
! */
!
! vlen = strlen(val);
!
! while (*s && (p = strstr(s, val)) != NULL) {
! /* Copy from start to p */
! *p = '\0';
! if (safe_str(start, tbuf1, &tbufp)) {
too_long = 1;
break;
}
if (!ansi_long_flag) {
! if (safe_str(start, tbuf_ansi, &tbufap))
ansi_long_flag = 1;
}
! s = p + vlen;
! start = s;
/* Copy in r */
! if (safe_str(r, tbuf1, &tbufp)) {
too_long = 1;
break;
}
--- 718,780 ----
if (safe_format(tbuf_ansi, &tbufap, "%s%s%s%s", ANSI_HILITE, r, ANSI_NORMAL,
s))
ansi_long_flag = 1;
+ } else if (!*val) {
+ /* insert replacement string between every character */
+ ansi_string *haystack;
+ size_t last = 0;
+ int too_long = 0;
+
+ haystack = parse_ansi_string(s);
+
+ /* Add one at the start */
+ if (!safe_strl(r, rlen, tbuf1, &tbufp)) {
+ for (last = 0; last < haystack->len; last++) {
+ /* Add the next character */
+ if (safe_ansi_string(haystack, last, 1, tbuf1, &tbufp)) {
+ too_long = 1;
+ break;
+ }
+ if (!ansi_long_flag) {
+ if (safe_ansi_string(haystack, last, 1, tbuf_ansi, &tbufap))
+ ansi_long_flag = 1;
+ }
+ /* Copy in r */
+ if (safe_strl(r, rlen, tbuf1, &tbufp)) {
+ too_long = 1;
+ break;
+ }
+ if (!ansi_long_flag) {
+ if (safe_format(tbuf_ansi, &tbufap, "%s%s%s", ANSI_HILITE, r,
+ ANSI_NORMAL))
+ ansi_long_flag = 1;
+ }
+ }
+ }
+ free_ansi_string(haystack);
} else {
/* find and replace */
! ansi_string *haystack;
! size_t last = 0;
! char *p;
int too_long = 0;
! haystack = parse_ansi_string(s);
!
! while (last < haystack->len
! && (p = strstr(haystack->text + last, val)) != NULL) {
! if (safe_ansi_string(haystack, last, p - (haystack->text + last),
! tbuf1, &tbufp)) {
too_long = 1;
break;
}
if (!ansi_long_flag) {
! if (safe_ansi_string(haystack, last, p - (haystack->text + last),
! tbuf_ansi, &tbufap))
ansi_long_flag = 1;
}
!
/* Copy in r */
! if (safe_strl(r, rlen, tbuf1, &tbufp)) {
too_long = 1;
break;
}
***************
*** 750,764 ****
ANSI_NORMAL))
ansi_long_flag = 1;
}
}
! /* No more val's in the string */
! if (*s && !too_long) {
! safe_str(s, tbuf1, &tbufp);
if (!ansi_long_flag) {
! if (safe_str(s, tbuf_ansi, &tbufap))
ansi_long_flag = 1;
}
}
}
*tbufp = '\0';
--- 783,798 ----
ANSI_NORMAL))
ansi_long_flag = 1;
}
+ last = p - haystack->text + vlen;
}
! if (last < haystack->len && !too_long) {
! safe_ansi_string(haystack, last, haystack->len, tbuf1, &tbufp);
if (!ansi_long_flag) {
! if (safe_ansi_string(haystack, last, haystack->len, tbuf_ansi, &tbufap))
ansi_long_flag = 1;
}
}
+ free_ansi_string(haystack);
}
*tbufp = '\0';
*** 1_7_6.144/src/game.c Thu, 06 Mar 2003 11:56:40 -0600 dunemush (pennmush/c/10_game.c 1.50.1.8.1.1.1.1.2.1.1.1.2.1.1.4.1.1.1.1.1.1.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.2.1.1.1.2.1.1.1.1.1.1.1.1.1.5.1.3.1.2.1.2.1.1.1.1.1.1 660)
--- 1_7_6.153(w)/src/game.c Tue, 13 May 2003 12:48:14 -0500 dunemush (pennmush/c/10_game.c 1.50.1.8.1.1.1.1.2.1.1.1.2.1.1.4.1.1.1.1.1.1.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.2.1.1.1.2.1.1.1.1.1.1.1.1.1.5.1.3.1.2.1.2.1.1.1.1.1.1.1.1 660)
***************
*** 710,715 ****
--- 710,717 ----
if (DO_GLOBALS && (!GoodObject(MASTER_ROOM) || (!IsRoom(MASTER_ROOM))))
do_rawlog(LT_ERR, T("WARNING: Master room (#%d) is NOT a room."),
MASTER_ROOM);
+ if (!GoodObject(BASE_ROOM) || (!IsRoom(BASE_ROOM)))
+ do_rawlog(LT_ERR, T("WARNING: Base room (#%d) is NOT a room."), BASE_ROOM);
if (!GoodObject(GOD) || (!IsPlayer(GOD)))
do_rawlog(LT_ERR, T("WARNING: God (#%d) is NOT a player."), GOD);
*** 1_7_6.144/src/funstr.c Sat, 05 Apr 2003 17:36:15 -0600 dunemush (pennmush/c/13_funstr.c 1.28.1.1.1.2.1.4.1.6.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.3.1.5.1.3.1.2.1.1.1.1.1.1 660)
--- 1_7_6.153(w)/src/funstr.c Tue, 13 May 2003 12:48:14 -0500 dunemush (pennmush/c/13_funstr.c 1.28.1.1.1.2.1.4.1.6.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.3.1.5.1.3.1.2.1.1.1.1.1.1.1.1.1.1 660)
***************
*** 1376,1434 ****
/* ARGSUSED */
FUNCTION(fun_edit)
{
- int len;
- char *str, *f, *r;
int i;
! char prebuf[BUFFER_LEN], *prep;
! char postbuf[BUFFER_LEN], *postp;
! postp = postbuf;
! safe_str(args[0], postbuf, &postp);
! *postp = '\0';
for (i = 1; i < nargs - 1; i += 2) {
! /* Old postbuf is new prebuf */
! prep = prebuf;
! safe_str(postbuf, prebuf, &prep);
! *prep = '\0';
! str = prebuf; /* The current string */
f = args[i]; /* find this */
r = args[i + 1]; /* replace it with this */
! postp = postbuf;
/* Check for nothing to avoid infinite loop */
if (!*f && !*r)
continue;
! if (!strcmp(f, "$")) {
/* append */
! safe_str(str, postbuf, &postp);
! safe_str(r, postbuf, &postp);
! } else if (!strcmp(f, "^")) {
/* prepend */
! safe_str(r, postbuf, &postp);
! safe_str(str, postbuf, &postp);
} else {
! len = strlen(f);
! while (*str) {
! if (!strncmp(str, f, len)) {
! safe_str(r, postbuf, &postp);
! if (len)
! str += len;
! else {
! safe_chr(*str, postbuf, &postp);
! str++;
! }
! } else {
! safe_chr(*str, postbuf, &postp);
! str++;
! }
}
! if (!*f)
! safe_str(r, postbuf, &postp);
}
*postp = '\0';
}
! safe_str(postbuf, buff, bp);
}
FUNCTION(fun_brackets)
--- 1376,1438 ----
/* ARGSUSED */
FUNCTION(fun_edit)
{
int i;
! char *f, *r, *raw;
! ansi_string *prebuf;
! char postbuf[BUFFER_LEN], lastbuf[BUFFER_LEN], *postp;
! size_t rlen, flen;
! prebuf = parse_ansi_string(args[0]);
! raw = args[0];
for (i = 1; i < nargs - 1; i += 2) {
!
! postp = postbuf;
f = args[i]; /* find this */
r = args[i + 1]; /* replace it with this */
! flen = arglens[i];
! rlen = arglens[i + 1];
/* Check for nothing to avoid infinite loop */
if (!*f && !*r)
continue;
! if (flen == 1 && *f == '$') {
/* append */
! safe_str(raw, postbuf, &postp);
! safe_strl(r, rlen, postbuf, &postp);
! } else if (flen == 1 && *f == '^') {
/* prepend */
! safe_strl(r, rlen, postbuf, &postp);
! safe_str(raw, postbuf, &postp);
! } else if (!*f) {
! /* insert between every character */
! size_t last;
! safe_strl(r, rlen, postbuf, &postp);
! for (last = 0; last < prebuf->len; last++) {
! safe_ansi_string(prebuf, last, 1, postbuf, &postp);
! safe_strl(r, rlen, postbuf, &postp);
! }
} else {
! char *p;
! size_t last = 0;
!
! while (last < prebuf->len && (p = strstr(prebuf->text + last, f)) != NULL) {
! safe_ansi_string(prebuf, last, p - (prebuf->text + last),
! postbuf, &postp);
! safe_strl(r, rlen, postbuf, &postp);
! last = p - prebuf->text + flen;
}
! if (last < prebuf->len)
! safe_ansi_string(prebuf, last, prebuf->len, postbuf, &postp);
}
*postp = '\0';
+ free_ansi_string(prebuf);
+ prebuf = parse_ansi_string(postbuf);
+ strcpy(lastbuf, postbuf);
+ raw = lastbuf;
}
! safe_ansi_string(prebuf, 0, prebuf->len, buff, bp);
! free_ansi_string(prebuf);
}
FUNCTION(fun_brackets)
*** 1_7_6.144/src/extmail.c Thu, 26 Dec 2002 14:20:42 -0600 dunemush (pennmush/c/22_extmail.c 1.44.1.7.1.5.1.9.1.1.1.1 660)
--- 1_7_6.153(w)/src/extmail.c Tue, 13 May 2003 12:48:14 -0500 dunemush (pennmush/c/22_extmail.c 1.44.1.7.1.5.1.9.1.1.1.1.1.1 660)
***************
*** 394,399 ****
--- 394,400 ----
if (mail_match(player, mp, ms, i[Folder(mp)])) {
j++;
mp->read &= M_FMASK; /* Clear the folder */
+ mp->read &= ~M_CLEARED; /* Unclear it if it was marked cleared */
mp->read |= FolderBit(foldernum);
if (All(ms)) {
if (!notified) {
*** 1_7_6.144/src/destroy.c Mon, 02 Dec 2002 17:56:32 -0600 dunemush (pennmush/c/24_destroy.c 1.24.2.2.1.3.1.1.1.1.1.1.1.4.1.1 660)
--- 1_7_6.153(w)/src/destroy.c Tue, 13 May 2003 12:48:13 -0500 dunemush (pennmush/c/24_destroy.c 1.24.2.2.1.3.1.1.1.1.1.1.1.4.1.1.1.1 660)
***************
*** 228,234 ****
notify(player, T("Permission denied."));
return NOTHING;
}
! if (thing == PLAYER_START || thing == MASTER_ROOM || God(thing)) {
notify(player, T("That is too special to be destroyed."));
return NOTHING;
}
--- 228,235 ----
notify(player, T("Permission denied."));
return NOTHING;
}
! if (thing == PLAYER_START || thing == MASTER_ROOM || thing == BASE_ROOM
! || God(thing)) {
notify(player, T("That is too special to be destroyed."));
return NOTHING;
}
*** 1_7_6.144/hdrs/version.h Wed, 09 Apr 2003 13:49:37 -0500 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.9.1.1.1.17.1.2.1.8 660)
--- 1_7_6.153(w)/hdrs/version.h Tue, 13 May 2003 12:48:19 -0500 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.9.1.1.1.17.1.2.1.8 660)
***************
*** 1,2 ****
! #define VERSION "PennMUSH version 1.7.6 patchlevel 9 [04/09/2003]"
! #define SHORTVN "PennMUSH 1.7.6p9"
--- 1,2 ----
! #define VERSION "PennMUSH version 1.7.6 patchlevel 10 [05/13/2003]"
! #define SHORTVN "PennMUSH 1.7.6p10"
*** 1_7_6.144/src/pcre.c Thu, 05 Sep 2002 09:29:20 -0500 dunemush (pennmush/d/36_pcre.c 1.4.1.3.1.3.1.1.1.1.1.1.1.3 660)
--- 1_7_6.153(w)/src/pcre.c Tue, 13 May 2003 12:48:17 -0500 dunemush (pennmush/d/36_pcre.c 1.4.1.3.1.3.1.1.1.1.1.1.1.4 660)
***************
*** 2,15 ****
* Perl-Compatible Regular Expressions *
*************************************************/
! /*
! This is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language. See
the file Tech.Notes for some information on the internals.
Written by: Philip Hazel <ph10 at cam.ac.uk>
! Copyright (c) 1997-2001 University of Cambridge
-----------------------------------------------------------------------------
Permission is granted to anyone to use this software for any purpose on any
--- 2,15 ----
* Perl-Compatible Regular Expressions *
*************************************************/
!
! /* This is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language. See
the file Tech.Notes for some information on the internals.
Written by: Philip Hazel <ph10 at cam.ac.uk>
! Copyright (c) 1997-2003 University of Cambridge
-----------------------------------------------------------------------------
Permission is granted to anyone to use this software for any purpose on any
***************
*** 32,68 ****
-----------------------------------------------------------------------------
*/
! /*********** THIS IS AN ALTERED VERSION! ****************/
! /*
! This is an altered version of pcre. It has been altered by
! Alan Schwartz ("Javelin") and Shawn Wagner ("Raevnos") for
! inclusion in PennMUSH.
! Some changes include:
! * All pcre code combined into pcre.c/pcre.h pair
! * includes of config/confmagic.h
! * pcre_malloc and pcre_free changed to malloc and free
! * Deleted some never-used functions (pcre_version, pcre_info, etc.)
! * Tries to avoid infinitely-long backtracking (Raevnos)
! * Remove unused UTF-8 support.
! */
#include "config.h"
- #define BACKTRACK_LIMIT 2500
-
- #include <stdio.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stddef.h>
- #ifdef BACKTRACK_LIMIT
- #include <signal.h>
- #include <setjmp.h>
- extern sig_atomic_t cpu_time_limit_hit;
- #endif
#include "pcre.h"
#include "confmagic.h"
/* These are the public options that can change during matching. */
#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
--- 32,100 ----
-----------------------------------------------------------------------------
*/
! /* Modified by Shawn Wagner for PennMUSH to fit in one file and remove
! things we don't use, like a bunch of API functions and utf-8
! support. If you want the full thing, see http://www.pcre.org. */
#include "config.h"
#include <limits.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stddef.h>
#include "pcre.h"
#include "confmagic.h"
+ /* Bits of PCRE's config.h */
+ #define LINK_SIZE 2
+ #define MATCH_LIMIT 100000
+ #define NEWLINE '\n'
+
+ /* Bits of internal.h */
+ /* This header contains definitions that are shared between the different
+ modules, but which are not relevant to the outside. */
+
+
+ /* PCRE keeps offsets in its compiled code as 2-byte quantities by default.
+ These are used, for example, to link from the start of a subpattern to its
+ alternatives and its end. The use of 2 bytes per offset limits the size of the
+ compiled regex to around 64K, which is big enough for almost everybody.
+ However, I received a request for an even bigger limit. For this reason, and
+ also to make the code easier to maintain, the storing and loading of offsets
+ from the byte string is now handled by the macros that are defined here.
+
+ The macros are controlled by the value of LINK_SIZE. This defaults to 2 in
+ the config.h file, but can be overridden by using -D on the command line. This
+ is automated on Unix systems via the "configure" command. */
+
+ #define PUT(a,n,d) \
+ (a[n] = (d) >> 8), \
+ (a[(n)+1] = (d) & 255)
+
+ #define GET(a,n) \
+ (((a)[n] << 8) | (a)[(n)+1])
+
+ #define MAX_PATTERN_SIZE (1 << 16)
+
+
+ /* Convenience macro defined in terms of the others */
+
+ #define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE
+
+
+ /* PCRE uses some other 2-byte quantities that do not change when the size of
+ offsets changes. There are used for repeat counts and for other things such as
+ capturing parenthesis numbers in back references. */
+
+ #define PUT2(a,n,d) \
+ a[n] = (d) >> 8; \
+ a[(n)+1] = (d) & 255
+
+ #define GET2(a,n) \
+ (((a)[n] << 8) | (a)[(n)+1])
+
+ #define PUT2INC(a,n,d) PUT2(a,n,d), a += 2
+
/* These are the public options that can change during matching. */
#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
***************
*** 73,83 ****
significant end. Make sure they don't overlap, though now that we have expanded
to four bytes there is plenty of space. */
! #define PCRE_FIRSTSET 0x40000000 /* first_char is set */
! #define PCRE_REQCHSET 0x20000000 /* req_char is set */
#define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */
! #define PCRE_INGROUP 0x08000000 /* compiling inside a group */
! #define PCRE_ICHANGED 0x04000000 /* i option changes within regex */
/* Options for the "extra" block produced by pcre_study(). */
--- 105,114 ----
significant end. Make sure they don't overlap, though now that we have expanded
to four bytes there is plenty of space. */
! #define PCRE_FIRSTSET 0x40000000 /* first_byte is set */
! #define PCRE_REQCHSET 0x20000000 /* req_byte is set */
#define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */
! #define PCRE_ICHANGED 0x08000000 /* i option changes within regex */
/* Options for the "extra" block produced by pcre_study(). */
***************
*** 88,94 ****
#define PUBLIC_OPTIONS \
(PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \
! PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8)
#define PUBLIC_EXEC_OPTIONS \
(PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
--- 119,126 ----
#define PUBLIC_OPTIONS \
(PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \
! PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \
! PCRE_NO_AUTO_CAPTURE)
#define PUBLIC_EXEC_OPTIONS \
(PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
***************
*** 99,104 ****
--- 131,147 ----
#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
+ /* Negative values for the firstchar and reqchar variables */
+
+ #define REQ_UNSET (-2)
+ #define REQ_NONE (-1)
+
+ /* Flags added to firstbyte or reqbyte; a "non-literal" item is either a
+ variable-length repeat, or a anything other than literal characters. */
+
+ #define REQ_CASELESS 0x0100 /* indicates caselessness */
+ #define REQ_VARY 0x0200 /* reqbyte followed non-literal item */
+
/* Miscellaneous definitions */
typedef int BOOL;
***************
*** 106,254 ****
#define FALSE 0
#define TRUE 1
- #ifndef NEWLINE
- #define NEWLINE '\n'
- #endif
-
/* Escape items that are just an encoding of a particular data value. Note that
! ESC_N is defined as yet another macro, which is set in config.h to either \n
(the default) or \r (which some people want). */
! #ifndef ESC_E
! #define ESC_E 27
#endif
! #ifndef ESC_F
! #define ESC_F '\f'
#endif
! #ifndef ESC_N
! #define ESC_N NEWLINE
#endif
! #ifndef ESC_R
! #define ESC_R '\r'
#endif
! #ifndef ESC_T
! #define ESC_T '\t'
#endif
/* These are escaped items that aren't just an encoding of a particular data
value such as \n. They must have non-zero values, as check_escape() returns
their negation. Also, they must appear in the same order as in the opcode
! definitions below, up to ESC_z. The final one must be ESC_REF as subsequent
! values are used for \1, \2, \3, etc. There is a test in the code for an escape
! greater than ESC_b and less than ESC_Z to detect the types that may be
! repeated. 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_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w,
! ESC_Z, ESC_z, ESC_REF
};
/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
! OP_EOD must correspond in order to the list of escapes immediately above. */
enum {
! OP_END, /* End of pattern */
/* Values corresponding to backslashed metacharacters */
! OP_SOD, /* Start of data: \A */
! OP_NOT_WORD_BOUNDARY, /* \B */
! OP_WORD_BOUNDARY, /* \b */
! OP_NOT_DIGIT, /* \D */
! OP_DIGIT, /* \d */
! OP_NOT_WHITESPACE, /* \S */
! OP_WHITESPACE, /* \s */
! OP_NOT_WORDCHAR, /* \W */
! OP_WORDCHAR, /* \w */
! OP_EODN, /* End of data or \n at end of data: \Z. */
! OP_EOD, /* End of data: \z */
!
! OP_OPT, /* Set runtime options */
! OP_CIRC, /* Start of line - varies with multiline switch */
! OP_DOLL, /* End of line - varies with multiline switch */
! OP_ANY, /* Match any character */
! OP_CHARS, /* Match string of characters */
! OP_NOT, /* Match anything but the following char */
!
! OP_STAR, /* The maximizing and minimizing versions of */
! OP_MINSTAR, /* all these opcodes must come in pairs, with */
! OP_PLUS, /* the minimizing one second. */
! OP_MINPLUS, /* This first set applies to single characters */
! OP_QUERY,
! OP_MINQUERY,
! OP_UPTO, /* From 0 to n matches */
! OP_MINUPTO,
! OP_EXACT, /* Exactly n matches */
!
! OP_NOTSTAR, /* The maximizing and minimizing versions of */
! OP_NOTMINSTAR, /* all these opcodes must come in pairs, with */
! OP_NOTPLUS, /* the minimizing one second. */
! OP_NOTMINPLUS, /* This first set applies to "not" single characters */
! OP_NOTQUERY,
! OP_NOTMINQUERY,
! OP_NOTUPTO, /* From 0 to n matches */
! OP_NOTMINUPTO,
! OP_NOTEXACT, /* Exactly n matches */
!
! OP_TYPESTAR, /* The maximizing and minimizing versions of */
! OP_TYPEMINSTAR, /* all these opcodes must come in pairs, with */
! OP_TYPEPLUS, /* the minimizing one second. These codes must */
! OP_TYPEMINPLUS, /* be in exactly the same order as those above. */
! OP_TYPEQUERY, /* This set applies to character types such as \d */
! OP_TYPEMINQUERY,
! OP_TYPEUPTO, /* From 0 to n matches */
! OP_TYPEMINUPTO,
! OP_TYPEEXACT, /* Exactly n matches */
!
! OP_CRSTAR, /* The maximizing and minimizing versions of */
! OP_CRMINSTAR, /* all these opcodes must come in pairs, with */
! OP_CRPLUS, /* the minimizing one second. These codes must */
! OP_CRMINPLUS, /* be in exactly the same order as those above. */
! OP_CRQUERY, /* These are for character classes and back refs */
! OP_CRMINQUERY,
! OP_CRRANGE, /* These are different to the three seta above. */
! OP_CRMINRANGE,
!
! OP_CLASS, /* Match a character class */
! OP_REF, /* Match a back reference */
! OP_RECURSE, /* Match this pattern recursively */
!
! OP_ALT, /* Start of alternation */
! OP_KET, /* End of group that doesn't have an unbounded repeat */
! OP_KETRMAX, /* These two must remain together and in this */
! OP_KETRMIN, /* order. They are for groups the repeat for ever. */
/* The assertions must come before ONCE and COND */
! OP_ASSERT, /* Positive lookahead */
! OP_ASSERT_NOT, /* Negative lookahead */
! OP_ASSERTBACK, /* Positive lookbehind */
! OP_ASSERTBACK_NOT, /* Negative lookbehind */
! OP_REVERSE, /* Move pointer back - used in lookbehind assertions */
/* ONCE 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, /* Once matched, don't back up into the subpattern */
! OP_COND, /* Conditional group */
! OP_CREF, /* Used to hold an extraction string number (cond ref) */
! OP_BRAZERO, /* These two must remain together and in this */
! OP_BRAMINZERO, /* order. */
! OP_BRANUMBER, /* Used for extracting brackets whose number is greater
than can fit into an opcode. */
! OP_BRA /* This and greater values are used for brackets that
extract substrings up to a basic limit. After that,
use is made of OP_BRANUMBER. */
};
/* The highest extraction number before we have to start using additional
bytes. (Originally PCRE didn't have support for extraction counts highter than
this number.) The value is limited by the number of opcodes left after OP_BRA,
--- 149,391 ----
#define FALSE 0
#define TRUE 1
/* Escape items that are just an encoding of a particular data value. Note that
! ESC_n is defined as yet another macro, which is set in config.h to either \n
(the default) or \r (which some people want). */
! #ifndef ESC_e
! #define ESC_e 27
#endif
! #ifndef ESC_f
! #define ESC_f '\f'
#endif
! #ifndef ESC_n
! #define ESC_n NEWLINE
#endif
! #ifndef ESC_r
! #define ESC_r '\r'
#endif
! #ifndef ESC_t
! #define ESC_t '\t'
#endif
/* These are escaped items that aren't just an encoding of a particular data
value such as \n. They must have non-zero values, as check_escape() returns
their negation. Also, they must appear in the same order as in the opcode
! definitions below, up to ESC_z. There's a dummy for OP_ANY because it
! corresponds to "." rather than an escape sequence. The final one must be
! ESC_REF as subsequent values are used for \1, \2, \3, etc. There is are two
! tests in the code for an escape greater than ESC_b and less than ESC_Z to
! detect the types that may be repeated. These are the types that consume a
! character. 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_Z, ESC_z, ESC_E, ESC_Q, ESC_REF
};
+ /* Flag bits and data types for the extended class (OP_XCLASS) for classes that
+ contain UTF-8 characters with values greater than 255. */
+
+ #define XCL_NOT 0x01 /* Flag: this is a negative class */
+ #define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
+
+ #define XCL_END 0 /* Marks end of individual items */
+ #define XCL_SINGLE 1 /* Single item (one multibyte char) follows */
+ #define XCL_RANGE 2 /* A range (two multibyte chars) follows */
+
+
/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
! OP_EOD must correspond in order to the list of escapes immediately above.
! Note that whenever this list is updated, the two macro definitions that follow
! must also be updated to match. */
enum {
! OP_END, /* 0 End of pattern */
/* Values corresponding to backslashed metacharacters */
! OP_SOD, /* 1 Start of data: \A */
! OP_SOM, /* 2 Start of match (subject + offset): \G */
! OP_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_EODN, /* 13 End of data or \n at end of data: \Z. */
! OP_EOD, /* 14 End of data: \z */
!
! OP_OPT, /* 15 Set runtime options */
! OP_CIRC, /* 16 Start of line - varies with multiline switch */
! OP_DOLL, /* 17 End of line - varies with multiline switch */
! OP_CHARS, /* 18 Match string of characters */
! OP_NOT, /* 19 Match anything but the following char */
!
! OP_STAR, /* 20 The maximizing and minimizing versions of */
! OP_MINSTAR, /* 21 all these opcodes must come in pairs, with */
! OP_PLUS, /* 22 the minimizing one second. */
! OP_MINPLUS, /* 23 This first set applies to single characters */
! OP_QUERY, /* 24 */
! OP_MINQUERY, /* 25 */
! OP_UPTO, /* 26 From 0 to n matches */
! OP_MINUPTO, /* 27 */
! OP_EXACT, /* 28 Exactly n matches */
!
! OP_NOTSTAR, /* 29 The maximizing and minimizing versions of */
! OP_NOTMINSTAR, /* 30 all these opcodes must come in pairs, with */
! OP_NOTPLUS, /* 31 the minimizing one second. */
! OP_NOTMINPLUS, /* 32 This set applies to "not" single characters */
! OP_NOTQUERY, /* 33 */
! OP_NOTMINQUERY, /* 34 */
! OP_NOTUPTO, /* 35 From 0 to n matches */
! OP_NOTMINUPTO, /* 36 */
! OP_NOTEXACT, /* 37 Exactly n matches */
!
! OP_TYPESTAR, /* 38 The maximizing and minimizing versions of */
! OP_TYPEMINSTAR, /* 39 all these opcodes must come in pairs, with */
! OP_TYPEPLUS, /* 40 the minimizing one second. These codes must */
! OP_TYPEMINPLUS, /* 41 be in exactly the same order as those above. */
! OP_TYPEQUERY, /* 42 This set applies to character types such as \d */
! OP_TYPEMINQUERY, /* 43 */
! OP_TYPEUPTO, /* 44 From 0 to n matches */
! OP_TYPEMINUPTO, /* 45 */
! OP_TYPEEXACT, /* 46 Exactly n matches */
!
! OP_CRSTAR, /* 47 The maximizing and minimizing versions of */
! OP_CRMINSTAR, /* 48 all these opcodes must come in pairs, with */
! OP_CRPLUS, /* 49 the minimizing one second. These codes must */
! OP_CRMINPLUS, /* 50 be in exactly the same order as those above. */
! OP_CRQUERY, /* 51 These are for character classes and back refs */
! OP_CRMINQUERY, /* 52 */
! OP_CRRANGE, /* 53 These are different to the three seta above. */
! OP_CRMINRANGE, /* 54 */
!
! OP_CLASS, /* 55 Match a character class, chars < 256 only */
! OP_NCLASS, /* 56 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, /* 56 Extended class for handling UTF-8 chars within the
! class. This does both positive and negative. */
!
! OP_REF, /* 57 Match a back reference */
! OP_RECURSE, /* 58 Match a numbered subpattern (possibly recursive) */
! OP_CALLOUT, /* 59 Call out to external function if provided */
!
! OP_ALT, /* 60 Start of alternation */
! OP_KET, /* 61 End of group that doesn't have an unbounded repeat */
! OP_KETRMAX, /* 62 These two must remain together and in this */
! OP_KETRMIN, /* 63 order. They are for groups the repeat for ever. */
/* The assertions must come before ONCE and COND */
! OP_ASSERT, /* 64 Positive lookahead */
! OP_ASSERT_NOT, /* 65 Negative lookahead */
! OP_ASSERTBACK, /* 66 Positive lookbehind */
! OP_ASSERTBACK_NOT, /* 67 Negative lookbehind */
! OP_REVERSE, /* 68 Move pointer back - used in lookbehind assertions */
/* ONCE 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, /* 69 Once matched, don't back up into the subpattern */
! OP_COND, /* 70 Conditional group */
! OP_CREF, /* 71 Used to hold an extraction string number (cond ref) */
! OP_BRAZERO, /* 72 These two must remain together and in this */
! OP_BRAMINZERO, /* 73 order. */
! OP_BRANUMBER, /* 74 Used for extracting brackets whose number is greater
than can fit into an opcode. */
! OP_BRA /* 75 This and greater values are used for brackets that
extract substrings up to a basic limit. After that,
use is made of OP_BRANUMBER. */
};
+ /* WARNING: There is an implicit assumption in study.c that all opcodes are
+ less than 128 in value. This makes handling UTF-8 character sequences easier.
+ */
+
+
+ /* This macro defines textual names for all the opcodes. There are used only
+ for debugging, in pcre.c when DEBUG is defined, and also in pcretest.c. The
+ macro is referenced only in printint.c. */
+
+ #define OP_NAME_LIST \
+ "End", "\\A", "\\G", "\\B", "\\b", "\\D", "\\d", \
+ "\\S", "\\s", "\\W", "\\w", "Any", "Anybyte", "\\Z", "\\z", \
+ "Opt", "^", "$", "chars", "not", \
+ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \
+ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \
+ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \
+ "*", "*?", "+", "+?", "?", "??", "{", "{", \
+ "class", "nclass", "xclass", "Ref", "Recurse", "Callout", \
+ "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not", \
+ "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cond ref",\
+ "Brazero", "Braminzero", "Branumber", "Bra"
+
+
+ /* This macro defines the length of fixed length operations in the compiled
+ regex. The lengths are used when searching for specific things, and also in the
+ debugging printing of a compiled regex. We use a macro so that it can be
+ incorporated both into pcre.c and pcretest.c without being publicly exposed.
+
+ As things have been extended, some of these are no longer fixed lenths, but are
+ minima instead. For example, the length of a single-character repeat may vary
+ in UTF-8 mode. The code that uses this table must know about such things. */
+
+ #define OP_LENGTHS \
+ 1, /* End */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* \A, \G, \B, \B, \D, \d, \S, \s, \W, \w */ \
+ 1, 1, 1, 1, 2, 1, 1, /* Any, Anybyte, \Z, \z, Opt, ^, $ */ \
+ 2, /* Chars - the minimum length */ \
+ 2, /* not */ \
+ /* Positive single-char repeats */ \
+ 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** These are */ \
+ 4, 4, 4, /* upto, minupto, exact ** minima */ \
+ /* Negative single-char repeats */ \
+ 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \
+ 4, 4, 4, /* NOT upto, minupto, exact */ \
+ /* Positive type repeats */ \
+ 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \
+ 4, 4, 4, /* Type upto, minupto, exact */ \
+ /* Character class & ref repeats */ \
+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \
+ 5, 5, /* CRRANGE, CRMINRANGE */ \
+ 33, /* CLASS */ \
+ 33, /* NCLASS */ \
+ 0, /* XCLASS - variable length */ \
+ 3, /* REF */ \
+ 1+LINK_SIZE, /* RECURSE */ \
+ 2, /* CALLOUT */ \
+ 1+LINK_SIZE, /* Alt */ \
+ 1+LINK_SIZE, /* Ket */ \
+ 1+LINK_SIZE, /* KetRmax */ \
+ 1+LINK_SIZE, /* KetRmin */ \
+ 1+LINK_SIZE, /* Assert */ \
+ 1+LINK_SIZE, /* Assert not */ \
+ 1+LINK_SIZE, /* Assert behind */ \
+ 1+LINK_SIZE, /* Assert behind not */ \
+ 1+LINK_SIZE, /* Reverse */ \
+ 1+LINK_SIZE, /* Once */ \
+ 1+LINK_SIZE, /* COND */ \
+ 3, /* CREF */ \
+ 1, 1, /* BRAZERO, BRAMINZERO */ \
+ 3, /* BRANUMBER */ \
+ 1+LINK_SIZE /* BRA */ \
+
+
/* The highest extraction number before we have to start using additional
bytes. (Originally PCRE didn't have support for extraction counts highter than
this number.) The value is limited by the number of opcodes left after OP_BRA,
***************
*** 257,262 ****
--- 394,403 ----
#define EXTRACT_BASIC_MAX 150
+ /* A magic value for OP_CREF to indicate the "in recursion" condition. */
+
+ #define CREF_RECURSE 0xffff
+
/* The texts of compile-time error messages are defined as macros here so that
they can be accessed by the POSIX wrapper and converted into error codes. Yes,
I could have used error codes in the first place, but didn't feel like changing
***************
*** 274,282 ****
#define ERR10 "operand of unlimited repeat could match the empty string"
#define ERR11 "internal error: unexpected repeat"
#define ERR12 "unrecognized character after (?"
! #define ERR13 "unused error"
#define ERR14 "missing )"
! #define ERR15 "back reference to non-existent subpattern"
#define ERR16 "erroffset passed as NULL"
#define ERR17 "unknown option bit(s) set"
#define ERR18 "missing ) after comment"
--- 415,423 ----
#define ERR10 "operand of unlimited repeat could match the empty string"
#define ERR11 "internal error: unexpected repeat"
#define ERR12 "unrecognized character after (?"
! #define ERR13 "POSIX named classes are supported only within a class"
#define ERR14 "missing )"
! #define ERR15 "reference to non-existent subpattern"
#define ERR16 "erroffset passed as NULL"
#define ERR17 "unknown option bit(s) set"
#define ERR18 "missing ) after comment"
***************
*** 290,302 ****
#define ERR26 "malformed number after (?("
#define ERR27 "conditional group contains more than two branches"
#define ERR28 "assertion expected after (?("
! #define ERR29 "(?p must be followed by )"
#define ERR30 "unknown POSIX class name"
#define ERR31 "POSIX collating elements are not supported"
#define ERR32 "this version of PCRE is not compiled with PCRE_UTF8 support"
! #define ERR33 "characters with values > 255 are not yet supported in classes"
#define ERR34 "character value in \\x{...} sequence is too large"
#define ERR35 "invalid condition (?(0)"
/* All character handling must be done as unsigned characters. Otherwise there
are problems with top-bit-set characters and functions such as isspace().
--- 431,451 ----
#define ERR26 "malformed number after (?("
#define ERR27 "conditional group contains more than two branches"
#define ERR28 "assertion expected after (?("
! #define ERR29 "(?R or (?digits must be followed by )"
#define ERR30 "unknown POSIX class name"
#define ERR31 "POSIX collating elements are not supported"
#define ERR32 "this version of PCRE is not compiled with PCRE_UTF8 support"
! #define ERR33 "spare error"
#define ERR34 "character value in \\x{...} sequence is too large"
#define ERR35 "invalid condition (?(0)"
+ #define ERR36 "\\C not allowed in lookbehind assertion"
+ #define ERR37 "PCRE does not support \\L, \\l, \\N, \\P, \\p, \\U, \\u, or \\X"
+ #define ERR38 "number after (?C is > 255"
+ #define ERR39 "closing ) for (?C expected"
+ #define ERR40 "recursive call could loop indefinitely"
+ #define ERR41 "unrecognized character after (?P"
+ #define ERR42 "syntax error after (?P"
+ #define ERR43 "two named groups have the same name"
/* All character handling must be done as unsigned characters. Otherwise there
are problems with top-bit-set characters and functions such as isspace().
***************
*** 307,334 ****
typedef unsigned char uschar;
! /* The real format of the start of the pcre block; the actual code vector
! runs on as long as necessary after the end. */
typedef struct real_pcre {
unsigned long int magic_number;
! size_t size;
! const unsigned char *tables;
unsigned long int options;
unsigned short int top_bracket;
unsigned short int top_backref;
! uschar first_char;
! uschar req_char;
! uschar code[1];
} real_pcre;
! /* The real format of the extra block returned by pcre_study(). */
! typedef struct real_pcre_extra {
uschar options;
uschar start_bits[32];
! } real_pcre_extra;
!
/* Structure for passing "static" information around between the functions
doing the compiling, so that they are thread-safe. */
--- 456,484 ----
typedef unsigned char uschar;
! /* 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. */
typedef struct real_pcre {
unsigned long int magic_number;
! size_t size; /* Total that was malloced */
! const unsigned char *tables; /* Pointer to tables */
unsigned long int options;
unsigned short int top_bracket;
unsigned short int top_backref;
! unsigned short int first_byte;
! unsigned short int req_byte;
! unsigned short int name_entry_size; /* Size of any name items; 0 => none */
! unsigned short int name_count; /* Number of name items */
} real_pcre;
! /* The format of the block used to store data from pcre_study(). */
! typedef struct pcre_study_data {
! size_t size; /* Total that was malloced */
uschar options;
uschar start_bits[32];
! } pcre_study_data;
/* Structure for passing "static" information around between the functions
doing the compiling, so that they are thread-safe. */
***************
*** 338,350 ****
const uschar *fcc; /* Points to case-flipping table */
const uschar *cbits; /* Points to character type table */
const uschar *ctypes; /* Points to table of type maps */
} compile_data;
/* Structure for passing "static" information around between the functions
doing the matching, so that they are thread-safe. */
typedef struct match_data {
! int errorcode; /* As it says */
int *offset_vector; /* Offset vector */
int offset_end; /* One past the end */
int offset_max; /* The maximum usable for return data */
--- 488,528 ----
const uschar *fcc; /* Points to case-flipping table */
const uschar *cbits; /* Points to character type table */
const uschar *ctypes; /* Points to table of type maps */
+ const uschar *start_code; /* The start of the compiled code */
+ uschar *name_table; /* The name/number table */
+ int names_found; /* Number of entries so far */
+ int name_entry_size; /* Size of each entry */
+ int top_backref; /* Maximum back reference */
+ unsigned int backref_map; /* Bitmap of low back refs */
+ int req_varyopt; /* "After variable item" flag for reqbyte */
} compile_data;
+ /* Structure for maintaining a chain of pointers to the currently incomplete
+ branches, for testing for left recursion. */
+
+ typedef struct branch_chain {
+ struct branch_chain *outer;
+ uschar *current;
+ } branch_chain;
+
+ /* Structure for items in a linked list that represents an explicit recursive
+ call within the pattern. */
+
+ typedef struct recursion_info {
+ struct recursion_info *prev; /* 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 */
+ const uschar *save_start; /* Old value of md->start_match */
+ int *offset_save; /* Pointer to start of saved offsets */
+ int saved_max; /* Number of saved offsets */
+ } recursion_info;
+
/* Structure for passing "static" information around between the functions
doing the matching, so that they are thread-safe. */
typedef struct match_data {
! unsigned long int match_call_count; /* As it says */
! unsigned long int match_limit; /* As it says */
int *offset_vector; /* Offset vector */
int offset_end; /* One past the end */
int offset_max; /* The maximum usable for return data */
***************
*** 356,367 ****
BOOL utf8; /* UTF8 flag */
BOOL endonly; /* Dollar not before final \n */
BOOL notempty; /* Empty string match not wanted */
! const uschar *start_pattern; /* For use when recursing */
const uschar *start_subject; /* Start of the subject string */
const uschar *end_subject; /* End of the subject string */
const uschar *start_match; /* Start of this match attempt */
const uschar *end_match_ptr; /* Subject position at end match */
int end_offset_top; /* Highwater mark at end of match */
} match_data;
/* Bit definitions for entries in the pcre_ctypes table. */
--- 534,549 ----
BOOL utf8; /* UTF8 flag */
BOOL endonly; /* Dollar not before final \n */
BOOL notempty; /* Empty string match not wanted */
! const uschar *start_code; /* For use when recursing */
const uschar *start_subject; /* Start of the subject string */
const uschar *end_subject; /* End of the subject string */
const uschar *start_match; /* Start of this match attempt */
const uschar *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 */
+ int start_offset; /* The start offset value */
+ recursion_info *recursive; /* Linked list of recursion data */
+ void *callout_data; /* To pass back to callouts */
} match_data;
/* Bit definitions for entries in the pcre_ctypes table. */
***************
*** 398,560 ****
#define tables_length (ctypes_offset + 256)
/* End of internal.h */
!
! /* Define DEBUG to get debugging output on stdout. */
!
! /* #define DEBUG */
!
! /* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
! inline, and there are *still* stupid compilers about that don't like indented
! pre-processor statements. I suppose it's only been 10 years... */
!
! #ifdef DEBUG
! #define DPRINTF(p) printf p
! #else
! #define DPRINTF(p) /*nothing */
! #endif
!
! #ifdef BACKTRACK_LIMIT
! jmp_buf backtrack_jmp;
! static unsigned int backtrack_count = 0;
! #endif
!
! /* Maximum number of items on the nested bracket stacks at compile time. This
! applies to the nesting of all kinds of parentheses. It does not limit
! un-nested, non-capturing parentheses. This number can be made bigger if
! necessary - it is used to dimension one int and one unsigned char vector at
! compile time. */
!
! #define BRASTACK_SIZE 200
!
!
! /* The number of bytes in a literal character string above which we can't add
! any more is different when UTF-8 characters may be encountered. */
!
! #define MAXLIT 255
!
!
! /* Min and max values for the common repeats; for the maxima, 0 => infinity */
!
! static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
! static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
!
! /* Text forms of OP_ values and things, for debugging (not all used) */
!
! #ifdef DEBUG
! static const char *OP_names[] = {
! "End", "\\A", "\\B", "\\b", "\\D", "\\d",
! "\\S", "\\s", "\\W", "\\w", "\\Z", "\\z",
! "Opt", "^", "$", "Any", "chars", "not",
! "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
! "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
! "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
! "*", "*?", "+", "+?", "?", "??", "{", "{",
! "class", "Ref", "Recurse",
! "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not",
! "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cref",
! "Brazero", "Braminzero", "Branumber", "Bra"
! };
! #endif
!
! /* Table for handling escaped characters in the range '0'-'z'. Positive returns
! are simple data values; negative values are for special things like \d and so
! on. Zero means further processing is needed (for things like \x), or the escape
! is invalid. */
!
! static const short int escapes[] = {
! 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */
! 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */
! '@', -ESC_A, -ESC_B, 0, -ESC_D, 0, 0, 0, /* @ - G */
! 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
! 0, 0, 0, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */
! 0, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */
! '`', 7, -ESC_b, 0, -ESC_d, ESC_E, ESC_F, 0, /* ` - g */
! 0, 0, 0, 0, 0, 0, ESC_N, 0, /* h - o */
! 0, 0, ESC_R, -ESC_s, ESC_T, 0, 0, -ESC_w, /* p - w */
! 0, 0, -ESC_z /* x - z */
! };
!
! /* Tables of names of POSIX character classes and their lengths. The list is
! terminated by a zero length entry. The first three must be alpha, upper, lower,
! as this is assumed for handling case independence. */
!
! static const char *posix_names[] = {
! "alpha", "lower", "upper",
! "alnum", "ascii", "cntrl", "digit", "graph",
! "print", "punct", "space", "word", "xdigit"
! };
!
! static const uschar posix_name_lengths[] = {
! 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0
! };
!
! /* Table of class bit maps for each POSIX class; up to three may be combined
! to form the class. */
!
! static const int posix_class_maps[] = {
! cbit_lower, cbit_upper, -1, /* alpha */
! cbit_lower, -1, -1, /* lower */
! cbit_upper, -1, -1, /* upper */
! cbit_digit, cbit_lower, cbit_upper, /* alnum */
! cbit_print, cbit_cntrl, -1, /* ascii */
! cbit_cntrl, -1, -1, /* cntrl */
! cbit_digit, -1, -1, /* digit */
! cbit_graph, -1, -1, /* graph */
! cbit_print, -1, -1, /* print */
! cbit_punct, -1, -1, /* punct */
! cbit_space, -1, -1, /* space */
! cbit_word, -1, -1, /* word */
! cbit_xdigit, -1, -1 /* xdigit */
! };
!
!
! /* Definition to allow mutual recursion */
!
! static BOOL
! compile_regex(int, int, int *, uschar **, const uschar **, const char **,
! BOOL, int, int *, int *, compile_data *);
!
! /* Structure for building a chain of data that actually lives on the
! stack, 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. */
!
! typedef struct eptrblock {
! struct eptrblock *prev;
! const uschar *saved_eptr;
! } eptrblock;
!
! /* Flag bits for the match() function */
!
! #define match_condassert 0x01 /* Called to check a condition assertion */
! #define match_isgroup 0x02 /* Set if start of bracketed group */
!
!
!
! /*************************************************
! * Global variables *
! *************************************************/
!
! /* PCRE is thread-clean and doesn't use any global variables in the normal
! sense. However, it calls memory allocation and free functions via the two
! indirections below, which are can be changed by the caller, but are shared
! between all threads. */
!
! #define pcre_malloc malloc
! #define pcre_free free
!
! /*************************************************
! * Macros and tables for character handling *
! *************************************************/
!
! /* When UTF-8 encoding is being used, a character is no longer just a single
! byte. The macros for character handling generate simple sequences when used in
! byte-mode, and more complicated ones for UTF-8 characters. */
!
! #define GETCHARINC(c, eptr) c = *eptr++;
! #define GETCHARLEN(c, eptr, len) c = *eptr;
! #define BACKCHAR(eptr)
!
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
--- 580,586 ----
#define tables_length (ctypes_offset + 256)
/* End of internal.h */
! /* chartables.c */
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
***************
*** 705,711 ****
*/
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0- 7 */
! 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 8- 15 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16- 23 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24- 31 */
0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* - ' */
--- 731,737 ----
*/
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, /* - ' */
***************
*** 739,833 ****
}; /* 248-255 */
/* End of chartables.c */
!
!
!
! #ifdef DEBUG
/*************************************************
! * Debugging function to print chars *
*************************************************/
! /* Print a sequence of chars in printable format, stopping at the end of the
! subject if the requested.
Arguments:
! p points to characters
! length number to print
! is_subject TRUE if printing from within md->start_subject
! md pointer to matching data block, if is_subject is TRUE
! Returns: nothing
*/
! static void
! pchars(const uschar * p, int length, BOOL is_subject, match_data * md)
{
! int c;
! if (is_subject && length > md->end_subject - p)
! length = md->end_subject - p;
! while (length-- > 0)
! if (isprint(c = *(p++)))
! printf("%c", c);
! else
! printf("\\x%02x", c);
}
- #endif
-
-
-
/*************************************************
! * Handle escapes *
*************************************************/
! /* This function is called when a \ has been encountered. It either returns a
! positive value for a simple escape such as \n, or a negative value which
! encodes one of the more complicated things such as \d. When UTF-8 is enabled,
! a positive value greater than 255 may be returned. On entry, ptr is pointing at
! the \. On exit, it is on the final character of the escape sequence.
!
! Arguments:
! ptrptr points to the pattern position pointer
! errorptr points to the pointer to the error message
! bracount number of previous extracting brackets
! options the options bits
! isclass TRUE if inside a character class
! cd pointer to char tables block
! Returns: zero or positive => a data character
! negative => a special escape sequence
! on error, errorptr is set
*/
! static int
! check_escape(const uschar ** ptrptr, const char **errorptr, int bracount,
! int options, BOOL isclass, compile_data * cd)
{
! const uschar *ptr = *ptrptr;
! int c, i;
! /* If backslash is at the end of the pattern, it's an error. */
! c = *(++ptr);
! if (c == 0)
! *errorptr = ERR1;
! /* Digits or letters may have special meaning; all others are literals. */
! else if (c < '0' || c > 'z') {
! }
! /* Do an initial lookup in a table. A non-zero result is something that can be
! returned immediately. Otherwise further processing may be required. */
! else if ((i = escapes[c - '0']) != 0)
! c = i;
/* Escapes that need further processing, or are illegal. */
else {
const uschar *oldptr;
switch (c) {
/* The handling of escape sequences consisting of a string of digits
starting with one that is not zero is not straightforward. By experiment,
the way Perl works seems to be as follows:
--- 765,1521 ----
}; /* 248-255 */
/* End of chartables.c */
! /* get.c */
/*************************************************
! * Copy captured string to given buffer *
*************************************************/
! /* This function copies a single captured substring into a given buffer.
! Note that we use memcpy() rather than strncpy() in case there are binary zeros
! in the string.
Arguments:
! subject the subject string that was matched
! ovector pointer to the offsets table
! stringcount the number of substrings that were captured
! (i.e. the yield of the pcre_exec call, unless
! that was zero, in which case it should be 1/3
! of the offset table size)
! stringnumber the number of the required substring
! buffer where to put the substring
! size the size of the buffer
! Returns: if successful:
! the length of the copied string, not including the zero
! that is put on the end; can be zero
! if not successful:
! PCRE_ERROR_NOMEMORY (-6) buffer too small
! PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
*/
! int
! pcre_copy_substring(const char *subject, int *ovector, int stringcount,
! int stringnumber, char *buffer, int size)
{
! int yield;
! if (stringnumber < 0 || stringnumber >= stringcount)
! return PCRE_ERROR_NOSUBSTRING;
! stringnumber *= 2;
! yield = ovector[stringnumber + 1] - ovector[stringnumber];
! if (size < yield + 1)
! return PCRE_ERROR_NOMEMORY;
! memcpy(buffer, subject + ovector[stringnumber], yield);
! buffer[yield] = 0;
! return yield;
}
+ /* End of get.c */
+ /* maketables.c */
/*************************************************
! * Create PCRE character tables *
*************************************************/
! /* This function builds a set of character tables for use by PCRE and returns
! a pointer to them. They are build using the ctype functions, and consequently
! their contents will depend upon the current locale setting. When compiled as
! part of the library, the store is obtained via malloc(), but when compiled
! inside dftables, use malloc().
! Arguments: none
! Returns: pointer to the contiguous block of data
*/
! const unsigned char *
! pcre_maketables(void)
{
! unsigned char *yield, *p;
! int i;
! yield = (unsigned char *) malloc(tables_length);
! if (yield == NULL)
! return NULL;
! p = yield;
! /* First comes the lower casing table */
! for (i = 0; i < 256; i++)
! *p++ = tolower(i);
! /* Next the case-flipping table */
! for (i = 0; i < 256; i++)
! *p++ = islower(i) ? toupper(i) : tolower(i);
!
! /* Then the character class tables. Don't try to be clever and save effort
! on exclusive ones - in some locales things may be different. Note that the
! table for "space" includes everything "isspace" gives, including VT in the
! default locale. This makes it work for the POSIX class [:space:]. */
!
! memset(p, 0, cbit_length);
! for (i = 0; i < 256; i++) {
! if (isdigit(i)) {
! p[cbit_digit + i / 8] |= 1 << (i & 7);
! p[cbit_word + i / 8] |= 1 << (i & 7);
! }
! if (isupper(i)) {
! p[cbit_upper + i / 8] |= 1 << (i & 7);
! p[cbit_word + i / 8] |= 1 << (i & 7);
! }
! if (islower(i)) {
! p[cbit_lower + i / 8] |= 1 << (i & 7);
! p[cbit_word + i / 8] |= 1 << (i & 7);
! }
! if (i == '_')
! p[cbit_word + i / 8] |= 1 << (i & 7);
! if (isspace(i))
! p[cbit_space + i / 8] |= 1 << (i & 7);
! if (isxdigit(i))
! p[cbit_xdigit + i / 8] |= 1 << (i & 7);
! if (isgraph(i))
! p[cbit_graph + i / 8] |= 1 << (i & 7);
! if (isprint(i))
! p[cbit_print + i / 8] |= 1 << (i & 7);
! if (ispunct(i))
! p[cbit_punct + i / 8] |= 1 << (i & 7);
! if (iscntrl(i))
! p[cbit_cntrl + i / 8] |= 1 << (i & 7);
! }
! p += cbit_length;
!
! /* Finally, the character type table. In this, we exclude VT from the white
! space chars, because Perl doesn't recognize it as such for \s and for comments
! within regexes. */
!
! for (i = 0; i < 256; i++) {
! int x = 0;
! if (i != 0x0b && isspace(i))
! x += ctype_space;
! if (isalpha(i))
! x += ctype_letter;
! if (isdigit(i))
! x += ctype_digit;
! if (isxdigit(i))
! x += ctype_xdigit;
! if (isalnum(i) || i == '_')
! x += ctype_word;
! if (strchr("*+?{^.$|()[", i) != 0)
! x += ctype_meta;
! *p++ = x;
! }
!
! return yield;
! }
!
! /* End of maketables.c */
! /* study.c */
!
! /*************************************************
! * Set a bit and maybe its alternate case *
! *************************************************/
!
! /* Given a character, set its bit in the table, and also the bit for the other
! version of a letter if we are caseless.
!
! Arguments:
! start_bits points to the bit map
! c is the character
! caseless the caseless flag
! cd the block with char table pointers
!
! Returns: nothing
! */
!
! static void
! set_bit(uschar * start_bits, int c, BOOL caseless, compile_data * cd)
! {
! start_bits[c / 8] |= (1 << (c & 7));
! if (caseless && (cd->ctypes[c] & ctype_letter) != 0)
! start_bits[cd->fcc[c] / 8] |= (1 << (cd->fcc[c] & 7));
! }
!
!
!
! /*************************************************
! * Create bitmap of starting chars *
! *************************************************/
!
! /* This function scans a compiled unanchored expression and attempts to build a
! bitmap of the set of initial characters. If it can't, it returns FALSE. As time
! goes by, we may be able to get more clever at doing this.
!
! Arguments:
! code points to an expression
! start_bits points to a 32-byte table, initialized to 0
! caseless the current state of the caseless flag
! utf8 TRUE if in UTF-8 mode
! cd the block with char table pointers
!
! Returns: TRUE if table built, FALSE otherwise
! */
!
! static BOOL
! set_start_bits(const uschar * code, uschar * start_bits, BOOL caseless,
! BOOL utf8, compile_data * cd)
! {
! register int c;
!
! /* This next statement and the later reference to dummy are here in order to
! trick the optimizer of the IBM C compiler for OS/2 into generating correct
! code. Apparently IBM isn't going to fix the problem, and we would rather not
! disable optimization (in this module it actually makes a big difference, and
! the pcre module can use all the optimization it can get). */
!
! volatile int dummy;
!
! do {
! const uschar *tcode = code + 1 + LINK_SIZE;
! BOOL try_next = TRUE;
!
! while (try_next) {
! /* If a branch starts with a bracket or a positive lookahead assertion,
! recurse to set bits from within them. That's all for this branch. */
!
! if ((int) *tcode >= OP_BRA || *tcode == OP_ASSERT) {
! if (!set_start_bits(tcode, start_bits, caseless, utf8, cd))
! return FALSE;
! try_next = FALSE;
! }
!
! else
! switch (*tcode) {
! default:
! return FALSE;
!
! /* Skip over callout */
!
! case OP_CALLOUT:
! tcode += 2;
! break;
!
! /* Skip over extended extraction bracket number */
!
! case OP_BRANUMBER:
! tcode += 3;
! break;
!
! /* Skip over lookbehind and negative lookahead assertions */
!
! case OP_ASSERT_NOT:
! case OP_ASSERTBACK:
! case OP_ASSERTBACK_NOT:
! do
! tcode += GET(tcode, 1);
! while (*tcode == OP_ALT);
! tcode += 1 + LINK_SIZE;
! break;
!
! /* Skip over an option setting, changing the caseless flag */
!
! case OP_OPT:
! caseless = (tcode[1] & PCRE_CASELESS) != 0;
! tcode += 2;
! break;
!
! /* BRAZERO does the bracket, but carries on. */
!
! case OP_BRAZERO:
! case OP_BRAMINZERO:
! if (!set_start_bits(++tcode, start_bits, caseless, utf8, cd))
! return FALSE;
! dummy = 1;
! do
! tcode += GET(tcode, 1);
! while (*tcode == OP_ALT);
! tcode += 1 + LINK_SIZE;
! break;
!
! /* Single-char * or ? sets the bit and tries the next item */
!
! case OP_STAR:
! case OP_MINSTAR:
! case OP_QUERY:
! case OP_MINQUERY:
! set_bit(start_bits, tcode[1], caseless, cd);
! tcode += 2;
! break;
!
! /* Single-char upto sets the bit and tries the next */
!
! case OP_UPTO:
! case OP_MINUPTO:
! set_bit(start_bits, tcode[3], caseless, cd);
! tcode += 4;
! break;
!
! /* At least one single char sets the bit and stops */
!
! case OP_EXACT: /* Fall through */
! tcode++;
!
! case OP_CHARS: /* Fall through */
! tcode++;
!
! case OP_PLUS:
! case OP_MINPLUS:
! set_bit(start_bits, tcode[1], caseless, cd);
! try_next = FALSE;
! break;
!
! /* Single character type sets the bits and stops */
!
! case OP_NOT_DIGIT:
! for (c = 0; c < 32; c++)
! start_bits[c] |= ~cd->cbits[c + cbit_digit];
! try_next = FALSE;
! break;
!
! case OP_DIGIT:
! for (c = 0; c < 32; c++)
! start_bits[c] |= cd->cbits[c + cbit_digit];
! try_next = FALSE;
! break;
!
! case OP_NOT_WHITESPACE:
! for (c = 0; c < 32; c++)
! start_bits[c] |= ~cd->cbits[c + cbit_space];
! try_next = FALSE;
! break;
!
! case OP_WHITESPACE:
! for (c = 0; c < 32; c++)
! start_bits[c] |= cd->cbits[c + cbit_space];
! try_next = FALSE;
! break;
!
! case OP_NOT_WORDCHAR:
! for (c = 0; c < 32; c++)
! start_bits[c] |= ~cd->cbits[c + cbit_word];
! try_next = FALSE;
! break;
!
! case OP_WORDCHAR:
! for (c = 0; c < 32; c++)
! start_bits[c] |= cd->cbits[c + cbit_word];
! try_next = FALSE;
! break;
!
! /* One or more character type fudges the pointer and restarts, knowing
! it will hit a single character type and stop there. */
!
! case OP_TYPEPLUS:
! case OP_TYPEMINPLUS:
! tcode++;
! break;
!
! case OP_TYPEEXACT:
! tcode += 3;
! break;
!
! /* Zero or more repeats of character types set the bits and then
! try again. */
!
! case OP_TYPEUPTO:
! case OP_TYPEMINUPTO:
! tcode += 2; /* Fall through */
!
! case OP_TYPESTAR:
! case OP_TYPEMINSTAR:
! case OP_TYPEQUERY:
! case OP_TYPEMINQUERY:
! switch (tcode[1]) {
! case OP_NOT_DIGIT:
! for (c = 0; c < 32; c++)
! start_bits[c] |= ~cd->cbits[c + cbit_digit];
! break;
!
! case OP_DIGIT:
! for (c = 0; c < 32; c++)
! start_bits[c] |= cd->cbits[c + cbit_digit];
! break;
!
! case OP_NOT_WHITESPACE:
! for (c = 0; c < 32; c++)
! start_bits[c] |= ~cd->cbits[c + cbit_space];
! break;
!
! case OP_WHITESPACE:
! for (c = 0; c < 32; c++)
! start_bits[c] |= cd->cbits[c + cbit_space];
! break;
!
! case OP_NOT_WORDCHAR:
! for (c = 0; c < 32; c++)
! start_bits[c] |= ~cd->cbits[c + cbit_word];
! break;
!
! case OP_WORDCHAR:
! for (c = 0; c < 32; c++)
! start_bits[c] |= cd->cbits[c + cbit_word];
! break;
! }
!
! tcode += 2;
! break;
!
! /* Character class where all the information is in a bit map: set the
! bits and either carry on or not, according to the repeat count. If it was
! a negative class, and we are operating with UTF-8 characters, any byte
! with the top-bit set is a potentially valid starter because it may start
! a character with a value > 255. (This is sub-optimal in that the
! character may be in the range 128-255, and those characters might be
! unwanted, but that's as far as we go for the moment.) */
!
! case OP_NCLASS:
! if (utf8)
! memset(start_bits + 16, 0xff, 16);
! /* Fall through */
!
! case OP_CLASS:
! {
! tcode++;
! for (c = 0; c < 32; c++)
! start_bits[c] |= tcode[c];
! tcode += 32;
! switch (*tcode) {
! case OP_CRSTAR:
! case OP_CRMINSTAR:
! case OP_CRQUERY:
! case OP_CRMINQUERY:
! tcode++;
! break;
!
! case OP_CRRANGE:
! case OP_CRMINRANGE:
! if (((tcode[1] << 8) + tcode[2]) == 0)
! tcode += 5;
! else
! try_next = FALSE;
! break;
!
! default:
! try_next = FALSE;
! break;
! }
! }
! break; /* End of bitmap class handling */
!
! } /* End of switch */
! } /* End of try_next loop */
!
! code += GET(code, 1); /* Advance to next branch */
! }
! while (*code == OP_ALT);
! return TRUE;
! }
!
!
!
! /*************************************************
! * Study a compiled expression *
! *************************************************/
!
! /* This function is handed a compiled expression that it must study to produce
! information that will speed up the matching. It returns a pcre_extra block
! which then gets handed back to pcre_exec().
!
! Arguments:
! re points to the compiled expression
! options contains option bits
! errorptr points to where to place error messages;
! set NULL unless error
!
! Returns: pointer to a pcre_extra block, with study_data filled in and the
! appropriate flag set;
! NULL on error or if no optimization possible
! */
!
! pcre_extra *
! pcre_study(const pcre * external_re, int options, const char **errorptr)
! {
! uschar start_bits[32];
! pcre_extra *extra;
! pcre_study_data *study;
! const real_pcre *re = (const real_pcre *) external_re;
! uschar *code = (uschar *) re + sizeof(real_pcre) +
! (re->name_count * re->name_entry_size);
! compile_data compile_block;
!
! *errorptr = NULL;
!
! if (re == NULL || re->magic_number != MAGIC_NUMBER) {
! *errorptr = "argument is not a compiled regular expression";
! return NULL;
! }
!
! if ((options & ~PUBLIC_STUDY_OPTIONS) != 0) {
! *errorptr = "unknown or incorrect option bit(s) set";
! return NULL;
! }
!
! /* For an anchored pattern, or an unanchored pattern that has a first char, or
! a multiline pattern that matches only at "line starts", no further processing
! at present. */
!
! if ((re->options & (PCRE_ANCHORED | PCRE_FIRSTSET | PCRE_STARTLINE)) != 0)
! return NULL;
!
! /* Set the character tables in the block which is passed around */
!
! compile_block.lcc = re->tables + lcc_offset;
! compile_block.fcc = re->tables + fcc_offset;
! compile_block.cbits = re->tables + cbits_offset;
! compile_block.ctypes = re->tables + ctypes_offset;
!
! /* See if we can find a fixed set of initial characters for the pattern. */
!
! memset(start_bits, 0, 32 * sizeof(uschar));
! if (!set_start_bits(code, start_bits, (re->options & PCRE_CASELESS) != 0,
! (re->options & PCRE_UTF8) != 0, &compile_block))
! return NULL;
!
! /* Get a pcre_extra block and a pcre_study_data block. The study data is put in
! the latter, which is pointed to by the former, which may also get additional
! data set later by the calling program. At the moment, the size of
! pcre_study_data is fixed. We nevertheless save it in a field for returning via
! the pcre_fullinfo() function so that if it becomes variable in the future, we
! don't have to change that code. */
!
! extra = (pcre_extra *) (malloc)
! (sizeof(pcre_extra) + sizeof(pcre_study_data));
!
! if (extra == NULL) {
! *errorptr = "failed to get memory";
! return NULL;
! }
!
! study = (pcre_study_data *) ((char *) extra + sizeof(pcre_extra));
! extra->flags = PCRE_EXTRA_STUDY_DATA;
! extra->study_data = study;
!
! study->size = sizeof(pcre_study_data);
! study->options = PCRE_STUDY_MAPPED;
! memcpy(study->start_bits, start_bits, sizeof(start_bits));
!
! return extra;
! }
!
! /* End of study.c */
! /* pcre.c */
! #define DPRINTF(p) /*nothing */
!
! /* Maximum number of items on the nested bracket stacks at compile time. This
! applies to the nesting of all kinds of parentheses. It does not limit
! un-nested, non-capturing parentheses. This number can be made bigger if
! necessary - it is used to dimension one int and one unsigned char vector at
! compile time. */
!
! #define BRASTACK_SIZE 200
!
!
! /* Maximum number of ints of offset to save on the stack for recursive calls.
! If the offset vector is bigger, malloc is used. This should be a multiple of 3,
! because the offset vector is always a multiple of 3 long. */
!
! #define REC_STACK_SAVE_MAX 30
!
!
! /* The number of bytes in a literal character string above which we can't add
! any more is set at 250 in order to allow for UTF-8 characters. (In theory it
! could be 255 when UTF-8 support is excluded, but that means that some of the
! test output would be different, which just complicates things.) */
!
! #define MAXLIT 250
!
!
! /* The maximum remaining length of subject we are prepared to search for a
! req_byte match. */
!
! #define REQ_BYTE_MAX 1000
!
!
! /* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
! the definition is next to the definition of the opcodes in internal.h. */
!
! static uschar OP_lengths[] = { OP_LENGTHS };
!
! /* Min and max values for the common repeats; for the maxima, 0 => infinity */
!
! static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
! static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
!
! /* Table for handling escaped characters in the range '0'-'z'. Positive returns
! are simple data values; negative values are for special things like \d and so
! on. Zero means further processing is needed (for things like \x), or the escape
! is invalid. */
!
! 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 */
! 0, -ESC_Q, 0, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */
! 0, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */
! '`', 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* ` - g */
! 0, 0, 0, 0, 0, 0, ESC_n, 0, /* h - o */
! 0, 0, ESC_r, -ESC_s, ESC_t, 0, 0, -ESC_w, /* p - w */
! 0, 0, -ESC_z /* x - z */
! };
!
! /* Tables of names of POSIX character classes and their lengths. The list is
! terminated by a zero length entry. The first three must be alpha, upper, lower,
! as this is assumed for handling case independence. */
!
! static const char *posix_names[] = {
! "alpha", "lower", "upper",
! "alnum", "ascii", "blank", "cntrl", "digit", "graph",
! "print", "punct", "space", "word", "xdigit"
! };
!
! static const uschar posix_name_lengths[] = {
! 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0
! };
!
! /* Table of class bit maps for each POSIX class; up to three may be combined
! to form the class. The table for [:blank:] is dynamically modified to remove
! the vertical space characters. */
!
! static const int posix_class_maps[] = {
! cbit_lower, cbit_upper, -1, /* alpha */
! cbit_lower, -1, -1, /* lower */
! cbit_upper, -1, -1, /* upper */
! cbit_digit, cbit_lower, cbit_upper, /* alnum */
! cbit_print, cbit_cntrl, -1, /* ascii */
! cbit_space, -1, -1, /* blank - a GNU extension */
! cbit_cntrl, -1, -1, /* cntrl */
! cbit_digit, -1, -1, /* digit */
! cbit_graph, -1, -1, /* graph */
! cbit_print, -1, -1, /* print */
! cbit_punct, -1, -1, /* punct */
! cbit_space, -1, -1, /* space */
! cbit_word, -1, -1, /* word - a Perl extension */
! cbit_xdigit, -1, -1 /* xdigit */
! };
!
!
! /* Definition to allow mutual recursion */
!
! static BOOL
! compile_regex(int, int, int *, uschar **, const uschar **, const char **,
! BOOL, int, int *, int *, branch_chain *, compile_data *);
!
! /* Structure for building a chain of data that actually lives on the
! stack, 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. */
!
! typedef struct eptrblock {
! struct eptrblock *prev;
! const uschar *saved_eptr;
! } eptrblock;
!
! /* Flag bits for the match() function */
!
! #define match_condassert 0x01 /* Called to check a condition assertion */
! #define match_isgroup 0x02 /* Set if start of bracketed group */
!
! /* Non-error returns from the match() function. Error returns are externally
! defined PCRE_ERROR_xxx codes, which are all negative. */
!
! #define MATCH_MATCH 1
! #define MATCH_NOMATCH 0
!
!
!
! /*************************************************
! * Global variables *
! *************************************************/
!
! /* PCRE is thread-clean and doesn't use any global variables in the normal
! sense. However, it calls memory allocation and free functions via the two
! indirections below, and it can optionally do callouts. These values can be
! changed by the caller, but are shared between all threads. However, when
! compiling for Virtual Pascal, things are done differently (see pcre.in). */
!
! int (*pcre_callout) (pcre_callout_block *) = NULL;
!
!
! /*************************************************
! * Macros and tables for character handling *
! *************************************************/
!
! #define GETCHAR(c, eptr) c = *eptr;
! #define GETCHARINC(c, eptr) c = *eptr++;
! #define GETCHARINCTEST(c, eptr) c = *eptr++;
! #define GETCHARLEN(c, eptr, len) c = *eptr;
! #define BACKCHAR(eptr)
!
! /*************************************************
! * Handle escapes *
! *************************************************/
!
! /* This function is called when a \ has been encountered. It either returns a
! positive value for a simple escape such as \n, or a negative value which
! encodes one of the more complicated things such as \d. When UTF-8 is enabled,
! a positive value greater than 255 may be returned. On entry, ptr is pointing at
! the \. On exit, it is on the final character of the escape sequence.
!
! Arguments:
! ptrptr points to the pattern position pointer
! errorptr points to the pointer to the error message
! bracount number of previous extracting brackets
! options the options bits
! isclass TRUE if inside a character class
! cd pointer to char tables block
!
! Returns: zero or positive => a data character
! negative => a special escape sequence
! on error, errorptr is set
! */
!
! static int
! check_escape(const uschar ** ptrptr, const char **errorptr, int bracount,
! int options, BOOL isclass, compile_data * cd)
! {
! const uschar *ptr = *ptrptr;
! int c, i;
!
! /* If backslash is at the end of the pattern, it's an error. */
!
! c = *(++ptr);
! if (c == 0)
! *errorptr = ERR1;
!
! /* Digits or letters may have special meaning; all others are literals. */
!
! else if (c < '0' || c > 'z') {
! }
!
! /* Do an initial lookup in a table. A non-zero result is something that can be
! returned immediately. Otherwise further processing may be required. */
!
! else if ((i = escapes[c - '0']) != 0)
! c = i;
/* Escapes that need further processing, or are illegal. */
else {
const uschar *oldptr;
switch (c) {
+ /* A number of Perl escapes are not handled by PCRE. We give an explicit
+ error. */
+
+ case 'l':
+ case 'L':
+ case 'N':
+ case 'p':
+ case 'P':
+ case 'u':
+ case 'U':
+ case 'X':
+ *errorptr = ERR37;
+ break;
+
/* The handling of escape sequences consisting of a string of digits
starting with one that is not zero is not straightforward. By experiment,
the way Perl works seems to be as follows:
***************
*** 1036,1052 ****
/*************************************************
* Find the fixed length of a pattern *
*************************************************/
/* Scan a pattern and compute the fixed length of subject that will match it,
if the length is fixed. This is needed for dealing with backward assertions.
Arguments:
code points to the start of the pattern (the bracket)
options the compiling options
! Returns: the fixed length, or -1 if there is no fixed length
*/
static int
--- 1724,1796 ----
/*************************************************
+ * Find first significant op code *
+ *************************************************/
+
+ /* This is called by several functions that scan a compiled expression looking
+ for a fixed first character, or an anchoring op code etc. It skips over things
+ that do not influence this. For some calls, a change of option is important.
+
+ Arguments:
+ code pointer to the start of the group
+ options pointer to external options
+ optbit the option bit whose changing is significant, or
+ zero if none are
+
+ Returns: pointer to the first significant opcode
+ */
+
+ static const uschar *
+ first_significant_code(const uschar * code, int *options, int optbit)
+ {
+ for (;;) {
+ switch ((int) *code) {
+ case OP_OPT:
+ if (optbit > 0 && ((int) code[1] & optbit) != (*options & optbit))
+ *options = (int) code[1];
+ code += 2;
+ break;
+
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ do
+ code += GET(code, 1);
+ while (*code == OP_ALT);
+ /* Fall through */
+
+ case OP_CALLOUT:
+ case OP_CREF:
+ case OP_BRANUMBER:
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_WORD_BOUNDARY:
+ code += OP_lengths[*code];
+ break;
+
+ default:
+ return code;
+ }
+ }
+ /* Control never reaches here */
+ }
+
+
+
+
+ /*************************************************
* Find the fixed length of a pattern *
*************************************************/
/* Scan a pattern and compute the fixed length of subject that will match it,
if the length is fixed. This is needed for dealing with backward assertions.
+ In UTF8 mode, the result is in characters rather than bytes.
Arguments:
code points to the start of the pattern (the bracket)
options the compiling options
! Returns: the fixed length, or -1 if there is no fixed length,
! or -2 if \C was encountered
*/
static int
***************
*** 1055,1061 ****
int length = -1;
register int branchlength = 0;
! register uschar *cc = code + 3;
/* Scan along the opcodes for this branch. If we get to the end of the
branch, check the length against that of the other branches. */
--- 1799,1805 ----
int length = -1;
register int branchlength = 0;
! register uschar *cc = code + 1 + LINK_SIZE;
/* Scan along the opcodes for this branch. If we get to the end of the
branch, check the length against that of the other branches. */
***************
*** 1072,1083 ****
case OP_COND:
d = find_fixedlength(cc, options);
if (d < 0)
! return -1;
branchlength += d;
do
! cc += (cc[1] << 8) + cc[2];
while (*cc == OP_ALT);
! cc += 3;
break;
/* Reached end of a branch; if it's a ket it is the end of a nested
--- 1816,1827 ----
case OP_COND:
d = find_fixedlength(cc, options);
if (d < 0)
! return d;
branchlength += d;
do
! cc += GET(cc, 1);
while (*cc == OP_ALT);
! cc += 1 + LINK_SIZE;
break;
/* Reached end of a branch; if it's a ket it is the end of a nested
***************
*** 1095,1101 ****
return -1;
if (*cc != OP_ALT)
return length;
! cc += 3;
branchlength = 0;
break;
--- 1839,1845 ----
return -1;
if (*cc != OP_ALT)
return length;
! cc += 1 + LINK_SIZE;
branchlength = 0;
break;
***************
*** 1106,1153 ****
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
do
! cc += (cc[1] << 8) + cc[2];
while (*cc == OP_ALT);
- cc += 3;
- break;
-
- /* Skip over things that don't match chars */
-
- case OP_REVERSE:
- case OP_BRANUMBER:
- case OP_CREF:
- cc++;
/* Fall through */
! case OP_OPT:
! cc++;
! /* Fall through */
case OP_SOD:
case OP_EOD:
case OP_EODN:
case OP_CIRC:
case OP_DOLL:
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
! cc++;
break;
/* Handle char strings. In UTF-8 mode we must count characters, not bytes.
This requires a scan of the string, unfortunately. We assume valid UTF-8
! strings, so all we do is reduce the length by one for byte whose bits are
! 10xxxxxx. */
case OP_CHARS:
branchlength += *(++cc);
cc += *cc + 1;
break;
! /* Handle exact repetitions */
case OP_EXACT:
case OP_TYPEEXACT:
! branchlength += (cc[1] << 8) + cc[2];
cc += 4;
break;
--- 1850,1897 ----
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
do
! cc += GET(cc, 1);
while (*cc == OP_ALT);
/* Fall through */
! /* Skip over things that don't match chars */
+ case OP_REVERSE:
+ case OP_BRANUMBER:
+ case OP_CREF:
+ case OP_OPT:
+ case OP_CALLOUT:
case OP_SOD:
+ case OP_SOM:
case OP_EOD:
case OP_EODN:
case OP_CIRC:
case OP_DOLL:
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
! cc += OP_lengths[*cc];
break;
/* Handle char strings. In UTF-8 mode we must count characters, not bytes.
This requires a scan of the string, unfortunately. We assume valid UTF-8
! strings, so all we do is reduce the length by one for every byte whose bits
! are 10xxxxxx. */
case OP_CHARS:
branchlength += *(++cc);
cc += *cc + 1;
break;
! /* Handle exact repetitions. The count is already in characters, but we
! need to skip over a multibyte character in UTF8 mode. */
case OP_EXACT:
+ branchlength += GET2(cc, 1);
+ cc += 4;
+ break;
+
case OP_TYPEEXACT:
! branchlength += GET2(cc, 1);
cc += 4;
break;
***************
*** 1164,1173 ****
--- 1908,1923 ----
cc++;
break;
+ /* The single-byte matcher isn't allowed */
+
+ case OP_ANYBYTE:
+ return -2;
/* Check a class for variable quantification */
+
case OP_CLASS:
+ case OP_NCLASS:
cc += 33;
switch (*cc) {
***************
*** 1179,1187 ****
case OP_CRRANGE:
case OP_CRMINRANGE:
! if ((cc[1] << 8) + cc[2] != (cc[3] << 8) + cc[4])
return -1;
! branchlength += (cc[1] << 8) + cc[2];
cc += 5;
break;
--- 1929,1937 ----
case OP_CRRANGE:
case OP_CRMINRANGE:
! if (GET2(cc, 1) != GET2(cc, 3))
return -1;
! branchlength += GET2(cc, 1);
cc += 5;
break;
***************
*** 1203,1208 ****
--- 1953,2154 ----
/*************************************************
+ * Scan compiled regex for numbered bracket *
+ *************************************************/
+
+ /* This little function scans through a compiled pattern until it finds a
+ capturing bracket with the given number.
+
+ Arguments:
+ code points to start of expression
+ utf8 TRUE in UTF-8 mode
+ number the required bracket number
+
+ Returns: pointer to the opcode for the bracket, or NULL if not found
+ */
+
+ static const uschar *
+ find_bracket(const uschar * code, int number)
+ {
+
+ for (;;) {
+ register int c = *code;
+ if (c == OP_END)
+ return NULL;
+ else if (c == OP_CHARS)
+ code += code[1] + OP_lengths[c];
+ else if (c > OP_BRA) {
+ int n = c - OP_BRA;
+ if (n > EXTRACT_BASIC_MAX)
+ n = GET2(code, 2 + LINK_SIZE);
+ if (n == number)
+ return (uschar *) code;
+ code += OP_lengths[OP_BRA];
+ } else {
+ code += OP_lengths[c];
+
+ /* In UTF-8 mode, opcodes that are followed by a character may be followed
+ by a multi-byte character. The length in the table is a minimum, so we have
+ to scan along to skip the extra characters. All opcodes are less than 128,
+ so we can use relatively efficient code. */
+
+ }
+ }
+ }
+
+
+
+ /*************************************************
+ * Scan compiled branch for non-emptiness *
+ *************************************************/
+
+ /* This function scans through a branch of a compiled pattern to see whether it
+ can match the empty string or not. It is called only from could_be_empty()
+ below. Note that first_significant_code() skips over assertions. If we hit an
+ unclosed bracket, we return "empty" - this means we've struck an inner bracket
+ whose current branch will already have been scanned.
+
+ Arguments:
+ code points to start of search
+ endcode points to where to stop
+ utf8 TRUE if in UTF8 mode
+
+ Returns: TRUE if what is matched could be empty
+ */
+
+ static BOOL
+ could_be_empty_branch(const uschar * code, const uschar * endcode, BOOL utf8)
+ {
+ register int c;
+ for (code = first_significant_code(code + 1 + LINK_SIZE, NULL, 0);
+ code < endcode;
+ code = first_significant_code(code + OP_lengths[c], NULL, 0)) {
+ const uschar *ccode;
+
+ c = *code;
+
+ if (c >= OP_BRA) {
+ BOOL empty_branch;
+ if (GET(code, 1) == 0)
+ return TRUE; /* Hit unclosed bracket */
+
+ /* Scan a closed bracket */
+
+ empty_branch = FALSE;
+ do {
+ if (!empty_branch && could_be_empty_branch(code, endcode, utf8))
+ empty_branch = TRUE;
+ code += GET(code, 1);
+ }
+ while (*code == OP_ALT);
+ if (!empty_branch)
+ return FALSE; /* All branches are non-empty */
+ code += 1 + LINK_SIZE;
+ c = *code;
+ }
+
+ else
+ switch (c) {
+ /* Check for quantifiers after a class */
+
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ ccode = code + 33;
+
+
+ switch (*ccode) {
+ case OP_CRSTAR: /* These could be empty; continue */
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ break;
+
+ default: /* Non-repeat => class must match */
+ case OP_CRPLUS: /* These repeats aren't empty */
+ case OP_CRMINPLUS:
+ return FALSE;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ if (GET2(ccode, 1) > 0)
+ return FALSE; /* Minimum > 0 */
+ break;
+ }
+ break;
+
+ /* Opcodes that must match a character */
+
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ANYBYTE:
+ case OP_CHARS:
+ case OP_NOT:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_EXACT:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTEXACT:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEEXACT:
+ return FALSE;
+
+ /* End of branch */
+
+ case OP_KET:
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_ALT:
+ return TRUE;
+
+ }
+ }
+
+ return TRUE;
+ }
+
+
+
+ /*************************************************
+ * Scan compiled regex for non-emptiness *
+ *************************************************/
+
+ /* This function is called to check for left recursive calls. We want to check
+ the current branch of the current pattern to see if it could match the empty
+ string. If it could, we must look outwards for branches at other levels,
+ stopping when we pass beyond the bracket which is the subject of the recursion.
+
+ Arguments:
+ code points to start of the recursion
+ endcode points to where to stop (current RECURSE item)
+ bcptr points to the chain of current (unclosed) branch starts
+ utf8 TRUE if in UTF-8 mode
+
+ Returns: TRUE if what is matched could be empty
+ */
+
+ static BOOL
+ could_be_empty(const uschar * code, const uschar * endcode,
+ branch_chain * bcptr, BOOL utf8)
+ {
+ while (bcptr != NULL && bcptr->current >= code) {
+ if (!could_be_empty_branch(bcptr->current, endcode, utf8))
+ return FALSE;
+ bcptr = bcptr->outer;
+ }
+ return TRUE;
+ }
+
+
+
+ /*************************************************
* Check for POSIX class syntax *
*************************************************/
***************
*** 1273,1336 ****
* Compile one branch *
*************************************************/
! /* Scan the pattern, compiling it into the code vector.
Arguments:
! options the option bits
! brackets points to number of extracting brackets used
! code points to the pointer to the current code point
! ptrptr points to the current pattern pointer
! errorptr points to pointer to error message
! optchanged set to the value of the last OP_OPT item compiled
! reqchar set to the last literal character required, else -1
! countlits set to count of mandatory literal characters
! cd contains pointers to tables
! Returns: TRUE on success
! FALSE, with *errorptr set on error
*/
static BOOL
! compile_branch(int options, int *brackets, uschar ** codeptr,
! const uschar ** ptrptr, const char **errorptr, int *optchanged,
! int *reqchar, int *countlits, compile_data * cd)
{
int repeat_type, op_type;
! int repeat_min, repeat_max;
! int bravalue, length;
int greedy_default, greedy_non_default;
! int prevreqchar;
int condcount = 0;
! int subcountlits = 0;
register int c;
register uschar *code = *codeptr;
uschar *tempcode;
const uschar *ptr = *ptrptr;
const uschar *tempptr;
uschar *previous = NULL;
uschar class[32];
/* Set up the default and non-default settings for greediness */
greedy_default = ((options & PCRE_UNGREEDY) != 0);
greedy_non_default = greedy_default ^ 1;
! /* Initialize no required char, and count of literals */
! *reqchar = prevreqchar = -1;
! *countlits = 0;
/* Switch on next character until the end of the branch */
for (;; ptr++) {
BOOL negate_class;
int class_charcount;
int class_lastchar;
int newoptions;
int skipbytes;
! int subreqchar;
c = *ptr;
if ((options & PCRE_EXTENDED) != 0) {
if ((cd->ctypes[c] & ctype_space) != 0)
continue;
--- 2219,2311 ----
* Compile one branch *
*************************************************/
! /* Scan the pattern, compiling it into the code vector. If the options are
! changed during the branch, the pointer is used to change the external options
! bits.
Arguments:
! optionsptr pointer to the option bits
! brackets points to number of extracting brackets used
! code points to the pointer to the current code point
! ptrptr points to the current pattern pointer
! errorptr points to pointer to error message
! firstbyteptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE)
! reqbyteptr set to the last literal character required, else < 0
! bcptr points to current branch chain
! cd contains pointers to tables etc.
! Returns: TRUE on success
! FALSE, with *errorptr set on error
*/
static BOOL
! compile_branch(int *optionsptr, int *brackets, uschar ** codeptr,
! const uschar ** ptrptr, const char **errorptr, int *firstbyteptr,
! int *reqbyteptr, branch_chain * bcptr, compile_data * cd)
{
int repeat_type, op_type;
! int repeat_min = 0, repeat_max = 0; /* To please picky compilers */
! int bravalue = 0;
! int length;
int greedy_default, greedy_non_default;
! int firstbyte, reqbyte;
! int zeroreqbyte, zerofirstbyte;
! int req_caseopt, reqvary, tempreqvary;
int condcount = 0;
! int options = *optionsptr;
register int c;
register uschar *code = *codeptr;
uschar *tempcode;
+ BOOL inescq = FALSE;
+ BOOL groupsetfirstbyte = FALSE;
const uschar *ptr = *ptrptr;
const uschar *tempptr;
uschar *previous = NULL;
uschar class[32];
+ BOOL utf8 = FALSE;
+
/* Set up the default and non-default settings for greediness */
greedy_default = ((options & PCRE_UNGREEDY) != 0);
greedy_non_default = greedy_default ^ 1;
! /* Initialize no first char, no required char. REQ_UNSET means "no char
! matching encountered yet". It gets changed to REQ_NONE if we hit something that
! matches a non-fixed char first char; reqbyte just remains unset if we never
! find one.
!
! When we hit a repe