[Pcre-svn] [173] code/trunk: Improve interfaces to substring…

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [173] code/trunk: Improve interfaces to substring functions, and fix bugs.
Revision: 173
          http://www.exim.org/viewvc/pcre2?view=rev&revision=173
Author:   ph10
Date:     2014-12-13 17:43:26 +0000 (Sat, 13 Dec 2014)


Log Message:
-----------
Improve interfaces to substring functions, and fix bugs.

Modified Paths:
--------------
    code/trunk/doc/pcre2_substring_copy_byname.3
    code/trunk/doc/pcre2_substring_copy_bynumber.3
    code/trunk/doc/pcre2_substring_get_byname.3
    code/trunk/doc/pcre2_substring_get_bynumber.3
    code/trunk/doc/pcre2api.3
    code/trunk/src/pcre2.h.in
    code/trunk/src/pcre2_error.c
    code/trunk/src/pcre2_match.c
    code/trunk/src/pcre2_substring.c
    code/trunk/testdata/testinput2
    code/trunk/testdata/testoutput2


Modified: code/trunk/doc/pcre2_substring_copy_byname.3
===================================================================
--- code/trunk/doc/pcre2_substring_copy_byname.3    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/doc/pcre2_substring_copy_byname.3    2014-12-13 17:43:26 UTC (rev 173)
@@ -24,8 +24,16 @@
 .sp
 The \fIbufflen\fP variable is updated to contain the length of the extracted
 string, excluding the trailing zero. The yield of the function is zero for
-success, PCRE2_ERROR_NOMEMORY if the buffer is too small, or
-PCRE2_ERROR_NOSUBSTRING if the string name is invalid.
+success or one of the following error numbers:
+.sp
+  PCRE2_ERROR_NOSUBSTRING   there are no groups of that name
+  PCRE2_ERROR_UNAVAILBLE    the ovector was too small for that group
+  PCRE2_ERROR_UNSET         the group did not participate in the match
+  PCRE2_ERROR_NOMEMORY      the buffer is not big enough   
+.sp
+If there is more than one group with the given name, the first one that is set 
+is returned. In this situation PCRE2_ERROR_UNSET means that no group with the 
+given name was set.
 .P
 There is a complete description of the PCRE2 native API in the
 .\" HREF


Modified: code/trunk/doc/pcre2_substring_copy_bynumber.3
===================================================================
--- code/trunk/doc/pcre2_substring_copy_bynumber.3    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/doc/pcre2_substring_copy_bynumber.3    2014-12-13 17:43:26 UTC (rev 173)
@@ -1,4 +1,4 @@
-.TH PCRE2_SUBSTRING_COPY_BYNUMBER 3 "01 December 2014" "PCRE2 10.00"
+.TH PCRE2_SUBSTRING_COPY_BYNUMBER 3 "13 December 2014" "PCRE2 10.00"
 .SH NAME
 PCRE2 - Perl-compatible regular expressions (revised API)
 .SH SYNOPSIS
@@ -24,9 +24,14 @@
   \fIbufflen\fP       Length of buffer
 .sp
 The \fIbufflen\fP variable is updated with the length of the extracted string,
-excluding the terminating zero. The yield of the function is zero for success,
-PCRE2_ERROR_NOMEMORY if the buffer was too small, or PCRE2_ERROR_NOSUBSTRING if
-the string number is invalid.
+excluding the terminating zero. The yield of the function is zero for success
+or one of the following error numbers:
+.sp
+  PCRE2_ERROR_NOSUBSTRING   there are no groups of that number
+  PCRE2_ERROR_UNAVAILBLE    the ovector was too small for that group
+  PCRE2_ERROR_UNSET         the group did not participate in the match
+  PCRE2_ERROR_NOMEMORY      the buffer is too small
+.sp
 .P
 There is a complete description of the PCRE2 native API in the
 .\" HREF


Modified: code/trunk/doc/pcre2_substring_get_byname.3
===================================================================
--- code/trunk/doc/pcre2_substring_get_byname.3    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/doc/pcre2_substring_get_byname.3    2014-12-13 17:43:26 UTC (rev 173)
@@ -25,9 +25,17 @@
 The memory in which the substring is placed is obtained by calling the same
 memory allocation function that was used for the match data block. The
 convenience function \fBpcre2_substring_free()\fP can be used to free it when
-it is no longer needed. The yield of the function is zero for success,
-PCRE2_ERROR_NOMEMORY if sufficient memory could not be obtained, or
-PCRE2_ERROR_NOSUBSTRING if the string name is invalid.
+it is no longer needed. The yield of the function is zero for success or one of
+the following error numbers:
+.sp
+  PCRE2_ERROR_NOSUBSTRING   there are no groups of that name
+  PCRE2_ERROR_UNAVAILBLE    the ovector was too small for that group
+  PCRE2_ERROR_UNSET         the group did not participate in the match
+  PCRE2_ERROR_NOMEMORY      memory could not be obtained
+.sp
+If there is more than one group with the given name, the first one that is set 
+is returned. In this situation PCRE2_ERROR_UNSET means that no group with the 
+given name was set.
 .P
 There is a complete description of the PCRE2 native API in the
 .\" HREF


Modified: code/trunk/doc/pcre2_substring_get_bynumber.3
===================================================================
--- code/trunk/doc/pcre2_substring_get_bynumber.3    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/doc/pcre2_substring_get_bynumber.3    2014-12-13 17:43:26 UTC (rev 173)
@@ -1,4 +1,4 @@
-.TH PCRE2_SUBSTRING_GET_BYNUMBER 3 "01 December 2014" "PCRE2 10.00"
+.TH PCRE2_SUBSTRING_GET_BYNUMBER 3 "13 December 2014" "PCRE2 10.00"
 .SH NAME
 PCRE2 - Perl-compatible regular expressions (revised API)
 .SH SYNOPSIS
@@ -25,9 +25,14 @@
 The memory in which the substring is placed is obtained by calling the same
 memory allocation function that was used for the match data block. The
 convenience function \fBpcre2_substring_free()\fP can be used to free it when
-it is no longer needed. The yield of the function is zero for success,
-PCRE2_ERROR_NOMEMORY if sufficient memory could not be obtained, or
-PCRE2_ERROR_NOSUBSTRING if the string number is invalid.
+it is no longer needed. The yield of the function is zero for success or one of
+the following error numbers:
+.sp
+  PCRE2_ERROR_NOSUBSTRING   there are no groups of that number
+  PCRE2_ERROR_UNAVAILBLE    the ovector was too small for that group
+  PCRE2_ERROR_UNSET         the group did not participate in the match
+  PCRE2_ERROR_NOMEMORY      memory could not be obtained
+.sp
 .P
 There is a complete description of the PCRE2 native API in the
 .\" HREF


Modified: code/trunk/doc/pcre2api.3
===================================================================
--- code/trunk/doc/pcre2api.3    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/doc/pcre2api.3    2014-12-13 17:43:26 UTC (rev 173)
@@ -1,4 +1,4 @@
-.TH PCRE2API 3 "01 December 2014" "PCRE2 10.00"
+.TH PCRE2API 3 "13 December 2014" "PCRE2 10.00"
 .SH NAME
 PCRE2 - Perl-compatible regular expressions (revised API)
 .sp
@@ -2307,10 +2307,19 @@
 .sp
   PCRE2_ERROR_NOSUBSTRING
 .sp
-No substring with the given number was captured. This could be because there is
-no capturing group of that number in the pattern, or because the group with
-that number did not participate in the match, or because the ovector was too
-small to capture that group.
+There is no substring with that number in the pattern, that is, the number is 
+greater than the number of capturing parentheses.
+.sp
+  PCRE2_ERROR_UNAVAILABLE
+.sp
+The substring number, though not greater than the number of captures in the 
+pattern, is greater than the number of slots in the ovector, so the substring 
+could not be captured.
+.sp
+  PCRE2_ERROR_UNSET
+.sp
+The substring did not participate in the match. For example, if the pattern is
+(abc)|(def) and the subject is "def", substring number 1 is unset.  
 .
 .
 .SH "EXTRACTING A LIST OF ALL CAPTURED SUBSTRINGS"
@@ -2345,7 +2354,7 @@
 subpattern \fIn\fP has not been used at all, it returns an empty string. This
 can be distinguished from a genuine zero-length substring by inspecting the
 appropriate offset in the ovector, which contain PCRE2_UNSET for unset
-substrings.
+substrings, or by calling \fBpcre2_substring_length_bynumber()\fP.
 .
 .
 .\" HTML <a name="extractbyname"></a>
@@ -2384,8 +2393,10 @@
 Given the number, you can extract the substring directly, or use one of the
 functions described above. For convenience, there are also "byname" functions
 that correspond to the "bynumber" functions, the only difference being that the
-second argument is a name instead of a number. However, if PCRE2_DUPNAMES is
-set and there are duplicate names, the behaviour may not be what you want.
+second argument is a name instead of a number. If PCRE2_DUPNAMES is
+set and there are duplicate names, these functions return the first named 
+string that is set. PCRE2_ERROR_UNSET is returned only if all groups of the 
+same name are unset.
 .P
 \fBWarning:\fP If the pattern uses the (?| feature to set up multiple
 subpatterns with the same number, as described in the
@@ -2485,9 +2496,9 @@
 .P
 When duplicates are present, \fBpcre2_substring_copy_byname()\fP and
 \fBpcre2_substring_get_byname()\fP return the first substring corresponding to
-the given name that is set. If none are set, PCRE2_ERROR_NOSUBSTRING is
-returned. The \fBpcre2_substring_number_from_name()\fP function returns
-the error PCRE2_ERROR_NOUNIQUESUBSTRING.
+the given name that is set. Only if none are set is PCRE2_ERROR_UNSET is
+returned. The \fBpcre2_substring_number_from_name()\fP function returns the
+error PCRE2_ERROR_NOUNIQUESUBSTRING when there are duplicate names.
 .P
 If you want to get full details of all captured substrings for a given name,
 you must use the \fBpcre2_substring_nametable_scan()\fP function. The first
@@ -2735,6 +2746,6 @@
 .rs
 .sp
 .nf
-Last updated: 01 December 2014
+Last updated: 13 December 2014
 Copyright (c) 1997-2014 University of Cambridge.
 .fi


Modified: code/trunk/src/pcre2.h.in
===================================================================
--- code/trunk/src/pcre2.h.in    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/src/pcre2.h.in    2014-12-13 17:43:26 UTC (rev 173)
@@ -80,20 +80,20 @@
 extern "C" {
 #endif


-/* The following options can be passed to pcre2_compile(), pcre2_match(), or
-pcre2_dfa_match(). PCRE2_NO_UTF_CHECK affects only the function to which it is
-passed. Put these bits at the most significant end of the options word so
+/* The following option bits can be passed to pcre2_compile(), pcre2_match(),
+or pcre2_dfa_match(). PCRE2_NO_UTF_CHECK affects only the function to which it
+is passed. Put these bits at the most significant end of the options word so
others can be added next to them */

 #define PCRE2_ANCHORED            0x80000000u
 #define PCRE2_NO_UTF_CHECK        0x40000000u


-/* Other options that can be passed to pcre2_compile(). They may affect
-compilation, JIT compilation, and/or interpretive execution. The following tags
-indicate which:
+/* The following option bits can be passed only to pcre2_compile(). However,
+they may affect compilation, JIT compilation, and/or interpretive execution.
+The following tags indicate which:

-C   alters what is compiled
-J   alters what JIT compiles
+C   alters what is compiled by pcre2_compile()
+J   alters what is compiled by pcre2_jit_compile()
 M   is inspected during pcre2_match() execution
 D   is inspected during pcre2_dfa_match() execution
 */
@@ -224,7 +224,8 @@
 #define PCRE2_ERROR_NULL              (-50)
 #define PCRE2_ERROR_RECURSELOOP       (-51)
 #define PCRE2_ERROR_RECURSIONLIMIT    (-52)
-#define PCRE2_ERROR_UNSET             (-53)
+#define PCRE2_ERROR_UNAVAILABLE       (-53)
+#define PCRE2_ERROR_UNSET             (-54)


/* Request types for pcre2_pattern_info() */


Modified: code/trunk/src/pcre2_error.c
===================================================================
--- code/trunk/src/pcre2_error.c    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/src/pcre2_error.c    2014-12-13 17:43:26 UTC (rev 173)
@@ -221,12 +221,13 @@
   "JIT stack limit reached\0"
   "match limit exceeded\0"
   "no more memory\0"
-  "unknown or unset substring\0"
+  "unknown substring\0"
   "non-unique substring name\0"
   /* 50 */
   "NULL argument passed\0"
   "nested recursion at the same subject position\0"
   "recursion limit exceeded\0"
+  "requested value is not available\0" 
   "requested value is not set\0"
   ;



Modified: code/trunk/src/pcre2_match.c
===================================================================
--- code/trunk/src/pcre2_match.c    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/src/pcre2_match.c    2014-12-13 17:43:26 UTC (rev 173)
@@ -7023,8 +7023,7 @@
   /* Set the return code to the number of captured strings, or 0 if there were
   too many to fit into the ovector. */


-  match_data->rc = ((mb->capture_last & OVFLBIT) != 0 &&
-                     mb->end_offset_top >= arg_offset_max)?
+  match_data->rc = ((mb->capture_last & OVFLBIT) != 0)?
     0 : mb->end_offset_top/2;


/* If there is space in the offset vector, set any unused pairs at the end to

Modified: code/trunk/src/pcre2_substring.c
===================================================================
--- code/trunk/src/pcre2_substring.c    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/src/pcre2_substring.c    2014-12-13 17:43:26 UTC (rev 173)
@@ -63,8 +63,9 @@


 Returns:         if successful: zero
                  if not successful, a negative error code:
-                   PCRE2_ERROR_NOMEMORY: buffer too small
-                   PCRE2_ERROR_NOSUBSTRING: no such captured substring
+                   (1) an error from nametable_scan()
+                   (2) an error from copy_bynumber()  
+                   (3) PCRE2_ERROR_UNSET: all named groups are unset
 */


 PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
@@ -83,7 +84,7 @@
   if (n < match_data->oveccount && match_data->ovector[n*2] != PCRE2_UNSET)
     return pcre2_substring_copy_bynumber(match_data, n, buffer, sizeptr);
   }
-return PCRE2_ERROR_NOSUBSTRING;
+return PCRE2_ERROR_UNSET;
 }



@@ -104,25 +105,24 @@
 Returns:         if successful: 0
                  if not successful, a negative error code:
                    PCRE2_ERROR_NOMEMORY: buffer too small
-                   PCRE2_ERROR_NOSUBSTRING: no such captured substring
+                   PCRE2_ERROR_NOSUBSTRING: no such substring
+                   PCRE2_ERROR_UNAVAILABLE: ovector too small
+                   PCRE2_ERROR_UNSET: substring is not set  
 */


 PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
 pcre2_substring_copy_bynumber(pcre2_match_data *match_data,
   uint32_t stringnumber, PCRE2_UCHAR *buffer, PCRE2_SIZE *sizeptr)
 {
-PCRE2_SIZE left, right;
-PCRE2_SIZE p = 0;
-PCRE2_SPTR subject = match_data->subject;
-if (stringnumber >= match_data->oveccount ||
-    stringnumber > match_data->code->top_bracket ||
-    (left = match_data->ovector[stringnumber*2]) == PCRE2_UNSET)
-  return PCRE2_ERROR_NOSUBSTRING;
-right = match_data->ovector[stringnumber*2+1];
-if (right - left + 1 > *sizeptr) return PCRE2_ERROR_NOMEMORY;
-while (left < right) buffer[p++] = subject[left++];
-buffer[p] = 0;
-*sizeptr = p;
+int rc;
+PCRE2_SIZE size;
+rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);
+if (rc < 0) return rc;
+if (size + 1 > *sizeptr) return PCRE2_ERROR_NOMEMORY;
+memcpy(buffer, match_data->subject + match_data->ovector[stringnumber*2], 
+  CU2BYTES(size));
+buffer[size] = 0;
+*sizeptr = size;
 return 0;
 }


@@ -144,8 +144,9 @@

 Returns:         if successful: zero
                  if not successful, a negative value:
-                   PCRE2_ERROR_NOMEMORY: couldn't get memory
-                   PCRE2_ERROR_NOSUBSTRING: no such captured substring
+                   (1) an error from nametable_scan()
+                   (2) an error from get_bynumber()  
+                   (3) PCRE2_ERROR_UNSET: all named groups are unset
 */


 PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
@@ -164,7 +165,7 @@
   if (n < match_data->oveccount && match_data->ovector[n*2] != PCRE2_UNSET)
     return pcre2_substring_get_bynumber(match_data, n, stringptr, sizeptr);
   }
-return PCRE2_ERROR_NOSUBSTRING;
+return PCRE2_ERROR_UNSET;
 }



@@ -182,37 +183,32 @@
   stringptr      where to put a pointer to the new memory
   sizeptr        where to put the size of the substring


-Returns:         if successful: zero
-                 if not successful a negative error code:
+Returns:         if successful: 0
+                 if not successful, a negative error code:
                    PCRE2_ERROR_NOMEMORY: failed to get memory
-                   PCRE2_ERROR_NOSUBSTRING: substring not present
+                   PCRE2_ERROR_NOSUBSTRING: no such substring
+                   PCRE2_ERROR_UNAVAILABLE: ovector too small
+                   PCRE2_ERROR_UNSET: substring is not set  
 */


 PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
 pcre2_substring_get_bynumber(pcre2_match_data *match_data,
   uint32_t stringnumber, PCRE2_UCHAR **stringptr, PCRE2_SIZE *sizeptr)
 {
-PCRE2_SIZE left, right;
-PCRE2_SIZE p = 0;
-void *block;
+int rc;
+PCRE2_SIZE size;
 PCRE2_UCHAR *yield;
-
-PCRE2_SPTR subject = match_data->subject;
-if (stringnumber >= match_data->oveccount ||
-    stringnumber > match_data->code->top_bracket ||
-    (left = match_data->ovector[stringnumber*2]) == PCRE2_UNSET)
-  return PCRE2_ERROR_NOSUBSTRING;
-right = match_data->ovector[stringnumber*2+1];
-
-block = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
-  (right-left+1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)match_data);
-if (block == NULL) return PCRE2_ERROR_NOMEMORY;
-
-yield = (PCRE2_UCHAR *)((char *)block + sizeof(pcre2_memctl));
-while (left < right) yield[p++] = subject[left++];
-yield[p] = 0;
+rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);
+if (rc < 0) return rc;
+yield = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
+  (size + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)match_data);
+if (yield == NULL) return PCRE2_ERROR_NOMEMORY;
+yield = (PCRE2_UCHAR *)(((char *)yield) + sizeof(pcre2_memctl));
+memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2], 
+  CU2BYTES(size));
+yield[size] = 0;
 *stringptr = yield;
-*sizeptr = p;
+*sizeptr = size;
 return 0;
 }


@@ -260,14 +256,14 @@
 PCRE2_SPTR entry;
 int entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,
   &first, &last);
-if (entrysize <= 0) return entrysize;
+if (entrysize < 0) return entrysize;
 for (entry = first; entry <= last; entry += entrysize)
   {
   uint32_t n = GET2(entry, 0);
   if (n < match_data->oveccount && match_data->ovector[n*2] != PCRE2_UNSET)
     return pcre2_substring_length_bynumber(match_data, n, sizeptr);
   }
-return PCRE2_ERROR_NOSUBSTRING;
+return PCRE2_ERROR_UNSET;
 }



@@ -276,27 +272,37 @@
 *        Get length of a numbered substring      *
 *************************************************/


-/* This function returns the length of a captured substring.
+/* This function returns the length of a captured substring. If the start is
+beyond the end (which can happen when \K is used in an assertion), it sets the
+length to zero.

 Arguments:
   match_data      pointer to match data
   stringnumber    the number of the required substring
-  sizeptr         where to put the length
+  sizeptr         where to put the length, if not NULL


-Returns:          0 if successful, else a negative error number
+Returns:         if successful: 0
+                 if not successful, a negative error code:
+                   PCRE2_ERROR_NOSUBSTRING: no such substring
+                   PCRE2_ERROR_UNAVAILABLE: ovector is too small
+                   PCRE2_ERROR_UNSET: substring is not set  
 */


 PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
 pcre2_substring_length_bynumber(pcre2_match_data *match_data,
   uint32_t stringnumber, PCRE2_SIZE *sizeptr)
 {
-if (stringnumber >= match_data->oveccount ||
-    stringnumber > match_data->code->top_bracket ||
-    match_data->ovector[stringnumber*2] == PCRE2_UNSET)
+PCRE2_SIZE left, right;
+if (stringnumber > match_data->code->top_bracket) 
   return PCRE2_ERROR_NOSUBSTRING;
-*sizeptr = match_data->ovector[stringnumber*2 + 1] -
-           match_data->ovector[stringnumber*2];
-return 0;
+if (stringnumber >= match_data->oveccount) 
+  return PCRE2_ERROR_UNAVAILABLE;
+if (match_data->ovector[stringnumber*2] == PCRE2_UNSET)
+  return PCRE2_ERROR_UNSET;
+left = match_data->ovector[stringnumber*2];
+right = match_data->ovector[stringnumber*2+1];
+if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left;
+return 0; 
 }



@@ -334,7 +340,8 @@
PCRE2_UCHAR *sp;
PCRE2_SIZE *ovector;

-if ((count = match_data->rc) < 0) return count;
+if ((count = match_data->rc) < 0) return count;   /* Match failed */
+if (count == 0) count = match_data->oveccount;    /* Ovector too small */


count2 = 2*count;
ovector = match_data->ovector;
@@ -342,7 +349,11 @@
if (lengthsptr != NULL) size += sizeof(PCRE2_SIZE) * count; /* For lengths */

for (i = 0; i < count2; i += 2)
- size += sizeof(PCRE2_UCHAR *) + CU2BYTES(ovector[i+1] - ovector[i] + 1);
+ {
+ size += sizeof(PCRE2_UCHAR *) + CU2BYTES(1);
+ if (ovector[i+1] > ovector[i]) size += CU2BYTES(ovector[i+1] - ovector[i]);
+ }
+
memp = PRIV(memctl_malloc)(size, (pcre2_memctl *)match_data);
if (memp == NULL) return PCRE2_ERROR_NOMEMORY;

@@ -362,7 +373,7 @@

for (i = 0; i < count2; i += 2)
{
- size = ovector[i+1] - ovector[i];
+ size = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;
memcpy(sp, match_data->subject + ovector[i], CU2BYTES(size));
*listp++ = sp;
if (lensp != NULL) *lensp++ = size;
@@ -400,8 +411,8 @@

/* This function scans the nametable for a given name, using binary chop. It
returns either two pointers to the entries in the table, or, if no pointers are
-given, the number of a group with the given name. If duplicate names are
-permitted, this may not be unique.
+given, the number of a unique group with the given name. If duplicate names are
+permitted, and the name is not unique, an error is generated.

 Arguments:
   code        the compiled regex
@@ -409,10 +420,12 @@
   firstptr    where to put the pointer to the first entry
   lastptr     where to put the pointer to the last entry


-Returns:      if firstptr and lastptr are NULL, a group number for a
-                unique substring, or PCRE2_ERROR_NOUNIQUESUBSTRING
-              otherwise, the length of each entry, or a negative number
-                (PCRE2_ERROR_NOSUBSTRING) if not found
+Returns:      PCRE2_ERROR_NOSUBSTRING if the name is not found
+              otherwise, if firstptr and lastptr are NULL:
+                a group number for a unique substring
+                else PCRE2_ERROR_NOUNIQUESUBSTRING
+              otherwise:
+                the length of each entry, having set firstptr and lastptr
 */


 PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
@@ -446,8 +459,8 @@
       if (PRIV(strcmp)(stringname, (last + entrysize + IMM2_SIZE)) != 0) break;
       last += entrysize;
       }
-    if (firstptr == NULL)
-      return (first == last)? (int)GET2(entry, 0) : PCRE2_ERROR_NOUNIQUESUBSTRING;
+    if (firstptr == NULL) return (first == last)? 
+      (int)GET2(entry, 0) : PCRE2_ERROR_NOUNIQUESUBSTRING;
     *firstptr = first;
     *lastptr = last;
     return entrysize;


Modified: code/trunk/testdata/testinput2
===================================================================
--- code/trunk/testdata/testinput2    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/testdata/testinput2    2014-12-13 17:43:26 UTC (rev 173)
@@ -4084,4 +4084,11 @@
 "(?(?=)?==)(((((((((?=)))))))))"
     a


+/(a)(b)|(c)/
+    XcX\=ovector=2,get=1,get=2,get=3,get=4,getall
+    
+/x(?=ab\K)/
+    xab\=get=0 
+    xab\=copy=0 
+
 # End of testinput2 


Modified: code/trunk/testdata/testoutput2
===================================================================
--- code/trunk/testdata/testoutput2    2014-12-02 11:06:13 UTC (rev 172)
+++ code/trunk/testdata/testoutput2    2014-12-13 17:43:26 UTC (rev 173)
@@ -993,7 +993,7 @@
  0: abcd
  1: a
  2: d
-Copy substring 5 failed (-48): unknown or unset substring
+Copy substring 5 failed (-48): unknown substring


/(.{20})/I
Capturing subpattern count = 1
@@ -1047,9 +1047,9 @@
2: <unset>
3: f
1G a (1)
-Get substring 2 failed (-48): unknown or unset substring
+Get substring 2 failed (-54): requested value is not set
3G f (1)
-Get substring 4 failed (-48): unknown or unset substring
+Get substring 4 failed (-48): unknown substring
0L adef
1L a
2L
@@ -1062,7 +1062,7 @@
1G bc (2)
2G bc (2)
3G f (1)
-Get substring 4 failed (-48): unknown or unset substring
+Get substring 4 failed (-48): unknown substring
0L bcdef
1L bc
2L bc
@@ -4363,7 +4363,7 @@
1: cd
2: gh
Number not found for group 'three'
-Copy substring 'three' failed (-48): unknown or unset substring
+Copy substring 'three' failed (-48): unknown substring

/(?P<Tes>)(?P<Test>)/IB
------------------------------------------------------------------
@@ -5731,7 +5731,7 @@
1: a1
2: a1
Number not found for group 'Z'
-Copy substring 'Z' failed (-48): unknown or unset substring
+Copy substring 'Z' failed (-48): unknown substring
C a1 (2) A (non-unique)

 /(?|(?<a>)(?<b>)(?<a>)|(?<a>)(?<b>)(?<a>))/I,dupnames
@@ -5772,7 +5772,7 @@
   C a (1) A (non-unique)
     cd\=copy=A
  0: cd
-Copy substring 'A' failed (-48): unknown or unset substring
+Copy substring 'A' failed (-54): requested value is not set


/^(?P<A>a)(?P<A>b)|cd(?P<A>ef)(?P<A>gh)/I,dupnames
Capturing subpattern count = 4
@@ -5817,7 +5817,7 @@
1: a1
2: a1
Number not found for group 'Z'
-Get substring 'Z' failed (-48): unknown or unset substring
+Get substring 'Z' failed (-48): unknown substring
G a1 (2) A (non-unique)

 /^(?P<A>a)(?P<A>b)/I,dupnames
@@ -5848,7 +5848,7 @@
   G a (1) A (non-unique)
     cd\=get=A
  0: cd
-Get substring 'A' failed (-48): unknown or unset substring
+Get substring 'A' failed (-54): requested value is not set


/^(?P<A>a)(?P<A>b)|cd(?P<A>ef)(?P<A>gh)/I,dupnames
Capturing subpattern count = 4
@@ -13659,11 +13659,11 @@

 /abc/replace=a$bad
     123abc
-Failed: error -48: unknown or unset substring
+Failed: error -48: unknown substring


 /abc/replace=a${A234567890123456789_123456789012}z
     123abc
-Failed: error -48: unknown or unset substring
+Failed: error -48: unknown substring


 /abc/replace=a${A23456789012345678901234567890123}z
     123abc
@@ -13715,4 +13715,26 @@
     a
 No match


+/(a)(b)|(c)/
+    XcX\=ovector=2,get=1,get=2,get=3,get=4,getall
+Matched, but too many substrings
+ 0: c
+ 1: <unset>
+Get substring 1 failed (-54): requested value is not set
+Get substring 2 failed (-53): requested value is not available
+Get substring 3 failed (-53): requested value is not available
+Get substring 4 failed (-48): unknown substring
+ 0L c
+ 1L 
+    
+/x(?=ab\K)/
+    xab\=get=0 
+Start of matched string is beyond its end - displaying from end to start.
+ 0: ab
+ 0G  (0)
+    xab\=copy=0 
+Start of matched string is beyond its end - displaying from end to start.
+ 0: ab
+ 0C  (0)
+
 # End of testinput2