+
+ start_match:
+ /* Match */
+ ret = silc_regex_buffer(src, 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 = *src;
+
+ if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
+ /* Advance buffer after match */
+ if (!silc_buffer_pull(src, (match.data - src->data)))
+ goto fail;
+ }
+
+ if (rflags & SILC_STR_REGEX_INCLUSIVE) {
+ inclusive_pos = src->tail - match.tail;
+ src->tail = match.tail;
+ }
+
+ /* Recursively format */
+ silc_va_copy(cp, ap);
+ ret_len = silc_buffer_sunformat_vp_i(stack, src, cp, TRUE);
+ va_end(cp);
+ if (ret_len < 0)
+ goto fail;
+
+ if (rflags & SILC_STR_REGEX_INCLUSIVE)
+ if (!silc_buffer_pull_tail(src, inclusive_pos))
+ goto fail;
+
+ /* Advance buffer after formatting */
+ if (!silc_buffer_pull(src, ret_len))
+ goto fail;
+
+ if (match_all && (!match_nl || silc_buffer_len(src) > 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. */
+ if (!silc_buffer_pull(src, (src->tail - src->data)))
+ goto fail;
+ if (!silc_buffer_pull_tail(src, silc_buffer_taillen(src)))
+ goto fail;
+
+ if (silc_buffer_len(src) > 0)
+ goto start_nl_match;
+ }
+
+ /* Skip to the next SILC_PARAM_END */
+ silc_buffer_sunformat_vp_i(NULL, src, ap, FALSE);
+ break;
+ }
+ break;
+
+ case SILC_PARAM_UICHAR:
+ {
+ unsigned char **x = va_arg(ap, unsigned char **);
+ SilcUInt32 len2 = va_arg(ap, SilcUInt32);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, len2);
+ if (silc_likely(len2 && x))
+ *x = src->data;
+ silc_buffer_pull(src, len2);
+ break;
+ }
+
+ case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
+ {
+ unsigned char **x = va_arg(ap, unsigned char **);
+ SilcUInt32 len2 = va_arg(ap, SilcUInt32);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, len2);
+ if (silc_likely(len2 && x)) {
+ *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
+ memcpy(*x, src->data, len2);
+ }
+ silc_buffer_pull(src, len2);
+ break;
+ }
+
+ case SILC_PARAM_UINT8:
+ {
+ unsigned char *x = va_arg(ap, unsigned char *);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, 1);
+ if (silc_likely(x))
+ *x = src->data[0];
+ silc_buffer_pull(src, 1);
+ break;
+ }
+
+ case SILC_PARAM_UINT16:
+ {
+ SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, 2);
+ if (silc_likely(x))
+ SILC_GET16_MSB(*x, src->data);
+ silc_buffer_pull(src, 2);
+ break;
+ }
+
+ case SILC_PARAM_UINT32:
+ {
+ SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, 4);
+ if (silc_likely(x))
+ SILC_GET32_MSB(*x, src->data);
+ silc_buffer_pull(src, 4);
+ break;
+ }
+
+ case SILC_PARAM_UINT64:
+ {
+ SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
+ if (silc_likely(x))
+ SILC_GET64_MSB(*x, src->data);
+ silc_buffer_pull(src, sizeof(SilcUInt64));