+
+ case SILC_PARAM_REGEX:
+ {
+ const char *regex = va_arg(ap, char *);
+ SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags);
+ SilcBufferStruct match;
+ SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
+ SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
+ SilcBool ret;
+ SilcUInt32 inclusive_pos = 0;
+ int matched = 0, ret_len;
+ va_list cp;
+
+ if (!process)
+ break;
+
+ if (!regex)
+ break;
+
+ if (match_nl) {
+ start_nl_match:
+ /* Match for '\n' in the buffer. If not found, treat as line
+ without '\n' (buffer has only one line, or this is last line). */
+ if (silc_regex_buffer(dst, "\n", &match, NULL))
+ dst->tail = match.tail;
+ }
+
+ start_match:
+ /* Match */
+ ret = silc_regex_buffer(dst, regex, &match, NULL);
+ ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
+ if (!ret) {
+ if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
+ goto fail;
+ }
+ goto end_match;
+ }
+ matched++;
+
+ if (rflags & SILC_STR_REGEX_NOT)
+ match = *dst;
+
+ if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
+ /* Advance buffer after match */
+ flen += (match.data - dst->data);
+ if (!silc_buffer_pull(dst, (match.data - dst->data)))
+ goto fail;
+ }
+
+ if (rflags & SILC_STR_REGEX_INCLUSIVE) {
+ inclusive_pos = dst->tail - match.tail;
+ dst->tail = match.tail;
+ }
+
+ /* Recursively format */
+ silc_va_copy(cp, ap);
+ ret_len = silc_buffer_sformat_vp_i(stack, dst, cp, TRUE);
+ va_end(cp);
+ if (ret_len < 0)
+ goto fail;
+
+ if (rflags & SILC_STR_REGEX_INCLUSIVE)
+ if (!silc_buffer_pull_tail(dst, inclusive_pos))
+ goto fail;
+
+ /* Advance buffer after formatting */
+ flen += ret_len;
+ if (!silc_buffer_pull(dst, ret_len))
+ goto fail;
+
+ if (match_all && (!match_nl || silc_buffer_len(dst) > 1))
+ goto start_match;
+
+ end_match:
+ if (match_nl) {
+ /* Go to next line, it is at the end of the data area. Adjust
+ the tail area of the target buffer to show rest of the buffer. */
+ flen += (dst->tail - dst->data);
+ if (!silc_buffer_pull(dst, (dst->tail - dst->data)))
+ goto fail;
+ if (!silc_buffer_pull_tail(dst, silc_buffer_taillen(dst)))
+ goto fail;
+
+ if (silc_buffer_len(dst) > 0)
+ goto start_nl_match;
+ }
+
+ /* Skip to the next SILC_PARAM_END */
+ silc_buffer_sformat_vp_i(NULL, NULL, ap, FALSE);
+ break;
+ }
+