| 1019 |
name it is given, it returns its number. Alternatively, if the name is NULL, it |
name it is given, it returns its number. Alternatively, if the name is NULL, it |
| 1020 |
returns when it reaches a given numbered subpattern. We know that if (?P< is |
returns when it reaches a given numbered subpattern. We know that if (?P< is |
| 1021 |
encountered, the name will be terminated by '>' because that is checked in the |
encountered, the name will be terminated by '>' because that is checked in the |
| 1022 |
first pass. Recursion is used to keep track of subpatterns that reset the |
first pass. Recursion is used to keep track of subpatterns that reset the |
| 1023 |
capturing group numbers - the (?| feature. |
capturing group numbers - the (?| feature. |
| 1024 |
|
|
| 1025 |
Arguments: |
Arguments: |
| 1028 |
name name to seek, or NULL if seeking a numbered subpattern |
name name to seek, or NULL if seeking a numbered subpattern |
| 1029 |
lorn name length, or subpattern number if name is NULL |
lorn name length, or subpattern number if name is NULL |
| 1030 |
xmode TRUE if we are in /x mode |
xmode TRUE if we are in /x mode |
| 1031 |
count pointer to the current capturing subpattern number (updated) |
count pointer to the current capturing subpattern number (updated) |
| 1032 |
|
|
| 1033 |
Returns: the number of the named subpattern, or -1 if not found |
Returns: the number of the named subpattern, or -1 if not found |
| 1034 |
*/ |
*/ |
| 1042 |
int hwm_count = start_count; |
int hwm_count = start_count; |
| 1043 |
BOOL dup_parens = FALSE; |
BOOL dup_parens = FALSE; |
| 1044 |
|
|
| 1045 |
/* If the first character is a parenthesis, check on the type of group we are |
/* If the first character is a parenthesis, check on the type of group we are |
| 1046 |
dealing with. The very first call may not start with a parenthesis. */ |
dealing with. The very first call may not start with a parenthesis. */ |
| 1047 |
|
|
| 1048 |
if (ptr[0] == CHAR_LEFT_PARENTHESIS) |
if (ptr[0] == CHAR_LEFT_PARENTHESIS) |
| 1049 |
{ |
{ |
| 1050 |
if (ptr[1] == CHAR_QUESTION_MARK && |
if (ptr[1] == CHAR_QUESTION_MARK && |
| 1051 |
ptr[2] == CHAR_VERTICAL_LINE) |
ptr[2] == CHAR_VERTICAL_LINE) |
| 1052 |
{ |
{ |
| 1053 |
ptr += 3; |
ptr += 3; |
| 1054 |
dup_parens = TRUE; |
dup_parens = TRUE; |
| 1055 |
} |
} |
| 1056 |
|
|
| 1057 |
/* Handle a normal, unnamed capturing parenthesis */ |
/* Handle a normal, unnamed capturing parenthesis */ |
| 1058 |
|
|
| 1059 |
else if (ptr[1] != CHAR_QUESTION_MARK && ptr[1] != CHAR_ASTERISK) |
else if (ptr[1] != CHAR_QUESTION_MARK && ptr[1] != CHAR_ASTERISK) |
| 1060 |
{ |
{ |
| 1061 |
*count += 1; |
*count += 1; |
| 1062 |
if (name == NULL && *count == lorn) return *count; |
if (name == NULL && *count == lorn) return *count; |
| 1063 |
ptr++; |
ptr++; |
| 1064 |
} |
} |
| 1065 |
|
|
| 1066 |
/* Handle a condition. If it is an assertion, just carry on so that it |
/* Handle a condition. If it is an assertion, just carry on so that it |
| 1067 |
is processed as normal. If not, skip to the closing parenthesis of the |
is processed as normal. If not, skip to the closing parenthesis of the |
| 1068 |
condition (there can't be any nested parens. */ |
condition (there can't be any nested parens. */ |
| 1069 |
|
|
| 1070 |
else if (ptr[2] == CHAR_LEFT_PARENTHESIS) |
else if (ptr[2] == CHAR_LEFT_PARENTHESIS) |
| 1071 |
{ |
{ |
| 1072 |
ptr += 2; |
ptr += 2; |
| 1073 |
if (ptr[1] != CHAR_QUESTION_MARK) |
if (ptr[1] != CHAR_QUESTION_MARK) |
| 1074 |
{ |
{ |
| 1075 |
while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; |
while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; |
| 1076 |
if (*ptr != 0) ptr++; |
if (*ptr != 0) ptr++; |
| 1077 |
} |
} |
| 1078 |
} |
} |
| 1079 |
|
|
| 1080 |
/* We have either (? or (* and not a condition */ |
/* We have either (? or (* and not a condition */ |
| 1081 |
|
|
| 1082 |
else |
else |
| 1083 |
{ |
{ |
| 1084 |
ptr += 2; |
ptr += 2; |
| 1085 |
if (*ptr == CHAR_P) ptr++; /* Allow optional P */ |
if (*ptr == CHAR_P) ptr++; /* Allow optional P */ |
| 1086 |
|
|
| 1087 |
/* We have to disambiguate (?<! and (?<= from (?<name> for named groups */ |
/* We have to disambiguate (?<! and (?<= from (?<name> for named groups */ |
| 1088 |
|
|
| 1089 |
if ((*ptr == CHAR_LESS_THAN_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK && |
if ((*ptr == CHAR_LESS_THAN_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK && |
| 1090 |
ptr[1] != CHAR_EQUALS_SIGN) || *ptr == CHAR_APOSTROPHE) |
ptr[1] != CHAR_EQUALS_SIGN) || *ptr == CHAR_APOSTROPHE) |
| 1091 |
{ |
{ |
| 1100 |
if (name != NULL && lorn == ptr - thisname && |
if (name != NULL && lorn == ptr - thisname && |
| 1101 |
strncmp((const char *)name, (const char *)thisname, lorn) == 0) |
strncmp((const char *)name, (const char *)thisname, lorn) == 0) |
| 1102 |
return *count; |
return *count; |
| 1103 |
} |
} |
| 1104 |
} |
} |
| 1105 |
} |
} |
| 1106 |
|
|
| 1107 |
/* Past any initial parenthesis handling, scan for parentheses or vertical |
/* Past any initial parenthesis handling, scan for parentheses or vertical |
| 1108 |
bars. */ |
bars. */ |
| 1109 |
|
|
| 1110 |
for (; *ptr != 0; ptr++) |
for (; *ptr != 0; ptr++) |
| 1185 |
} |
} |
| 1186 |
|
|
| 1187 |
/* Check for the special metacharacters */ |
/* Check for the special metacharacters */ |
| 1188 |
|
|
| 1189 |
if (*ptr == CHAR_LEFT_PARENTHESIS) |
if (*ptr == CHAR_LEFT_PARENTHESIS) |
| 1190 |
{ |
{ |
| 1191 |
int rc = find_parens_sub(&ptr, cd, name, lorn, xmode, count); |
int rc = find_parens_sub(&ptr, cd, name, lorn, xmode, count); |
| 1192 |
if (rc > 0) return rc; |
if (rc > 0) return rc; |
| 1193 |
if (*ptr == 0) goto FAIL_EXIT; |
if (*ptr == 0) goto FAIL_EXIT; |
| 1194 |
} |
} |
| 1195 |
|
|
| 1196 |
else if (*ptr == CHAR_RIGHT_PARENTHESIS) |
else if (*ptr == CHAR_RIGHT_PARENTHESIS) |
| 1197 |
{ |
{ |
| 1198 |
if (dup_parens && *count < hwm_count) *count = hwm_count; |
if (dup_parens && *count < hwm_count) *count = hwm_count; |
| 1199 |
*ptrptr = ptr; |
*ptrptr = ptr; |
| 1200 |
return -1; |
return -1; |
| 1201 |
} |
} |
| 1202 |
|
|
| 1203 |
else if (*ptr == CHAR_VERTICAL_LINE && dup_parens) |
else if (*ptr == CHAR_VERTICAL_LINE && dup_parens) |
| 1204 |
{ |
{ |
| 1205 |
if (*count > hwm_count) hwm_count = *count; |
if (*count > hwm_count) hwm_count = *count; |
| 1206 |
*count = start_count; |
*count = start_count; |
| 1207 |
} |
} |
| 1208 |
} |
} |
| 1209 |
|
|
| 1210 |
FAIL_EXIT: |
FAIL_EXIT: |
| 1251 |
does start with a parenthesis, find_parens_sub() will return when it hits the |
does start with a parenthesis, find_parens_sub() will return when it hits the |
| 1252 |
matching closing parens. That is why we have to have a loop. */ |
matching closing parens. That is why we have to have a loop. */ |
| 1253 |
|
|
| 1254 |
for (;;) |
for (;;) |
| 1255 |
{ |
{ |
| 1256 |
rc = find_parens_sub(&ptr, cd, name, lorn, xmode, &count); |
rc = find_parens_sub(&ptr, cd, name, lorn, xmode, &count); |
| 1257 |
if (rc > 0 || *ptr++ == 0) break; |
if (rc > 0 || *ptr++ == 0) break; |
| 1258 |
} |
} |
| 1259 |
|
|
| 1260 |
return rc; |
return rc; |
| 1261 |
} |
} |
| 1262 |
|
|