From nobody Sun Aug 24 19:29:38 2025 X-Original-To: dev-commits-ports-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4c93sV1mM7z65vZT; Sun, 24 Aug 2025 19:29:50 +0000 (UTC) (envelope-from eduardo@freebsd.org) Received: from smtp.freebsd.org (smtp.freebsd.org [IPv6:2610:1c1:1:606c::24b:4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "smtp.freebsd.org", Issuer "R13" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4c93sV0ws2z3CSd; Sun, 24 Aug 2025 19:29:50 +0000 (UTC) (envelope-from eduardo@freebsd.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1756063790; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=yYG4Nyue0kU4Z+S5h+hbPlOwyIKnkjO0KnCQ29YOiRo=; b=QDxDD72x6x3z3okpUnDV/QiPnC5eATn0qvAZQyC7Vw/UiDSTQj0L3RgruyI5jhoNU7lRFN 6dGByfOLaXDER6vOwmH5aGyU2kGhWTw2hY+KnYnTqprMi++/TCkc5gu3EVKQQzrrH2xufT wxZywq392K81YD9EJ51Cj/uXgXTnfb7nSvkxEv9SRYTK0J/RZIvuIwHuYRk9pakXCb1hGT WMHlCFp/9pYjKhZxWIUfsPTvSZVGtx6Z316/x7+L9w/XLCpzV5QCS7Cgoae1PmBVv8VCg9 OdPr5A3u4Q1dw+Z4l2YUM24aDE+3NMbSBn0NVnnrq1oSfmCe9K3Tnst5Lqd6KA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1756063790; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=yYG4Nyue0kU4Z+S5h+hbPlOwyIKnkjO0KnCQ29YOiRo=; b=CjVdT+JeWk5jhm0HUQRNgKdxWZUkG5M0+v3/EDk7q6SgN/cqFOob5/eRDxna5oXdAGkHCm jqaS42UW9qE0XyLOUPJ0zI8Gv+wIgOHx7S3q3ctz91uNLpLRZajlV0SqrQ/B+adKlPvblF 8SKfBVw6gC7vroSwf7E241v848pj0ROGLcvdcMFnNBTK/mPrPV6cg/Dg+lHsxTs0CFda9k KL6ZOevrCPuiQPPX86XJwzJ1P3pzEilcdn+oqysV1ghReoSL9lTbogiv25tjTiQBZurahD GxDvsHsgbiDrdw4O+2SBihEaQFM/dWRqBiKSoVUaEuYDpT2lFBPfF51SXTw2Sg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1756063790; a=rsa-sha256; cv=none; b=GxesoZZJNh1JushNli9YruEBZJy6AY8DrzSx+Q9o47Nf0AqXaxwFkOT4ZYoTeWBZ4Ovfd6 I1u2ELR57ByC4f8GN8vWhWZLmm5ZJ+vFE2KOgFXHErvpt5GVJLBfC5M6ItSu6kCpWOc+jl SHDrL1cuSRlL4P6xWKuyy8dHZESD2voY68ft/f0nHiL8qeNAFi7MAIb1DQVfTYfdwHa5Yg 4ib8p0Li7Md6eDdNhUfzhqjyfntf6RBOtTuFVpNSktR2t4pA93sDKCkSezIP2/Za23k7to XyKSnE7NjEt3YBJ0plUDSLpOL4K8EK3IcA/mjUzwZmqTiP101sWFcsJQm+VTBg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from mail-qv1-f50.google.com (mail-qv1-f50.google.com [209.85.219.50]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "smtp.gmail.com", Issuer "WR4" (verified OK)) (Authenticated sender: eduardo) by smtp.freebsd.org (Postfix) with ESMTPSA id 4c93sT6tJdz14wy; Sun, 24 Aug 2025 19:29:49 +0000 (UTC) (envelope-from eduardo@freebsd.org) Received: by mail-qv1-f50.google.com with SMTP id 6a1803df08f44-70bb5f71f31so5966066d6.1; Sun, 24 Aug 2025 12:29:49 -0700 (PDT) X-Forwarded-Encrypted: i=1; AJvYcCW6JycCmK2ErE0CAtlbsPIVe0ZDTAhFiqZ/x/y17rcciZyAXgbqjMfbNIn5y8PH4fEtViSZSwzT+5qAMQzB5s/+eppULU0=@freebsd.org, AJvYcCXQvL+Yn9xPfD0naDhjFlsT2IUbCWgn4NmKLhHDqEIJZlvQHkLLW3CW9S5tcg0oxGH6IDenhNwrYaVm35wLG1kuFgmCFvHfDA==@freebsd.org X-Gm-Message-State: AOJu0YyzncFiCKmHF+wpVdzf1fOmsIZkcvcP3roL5yg5fT/ue1WfWseW 4HpuBZYCiHazaetLHRPRDs/+dy9uhnX5vU4NgAO+SgL9A6H8MxcbITOGlihveFSl9gJnWXtgoO8 tn+iqy+t5//RYPrGaGajiXYygpk8uBqA= X-Google-Smtp-Source: AGHT+IGrQXIRHLvMNZpEXyIHafgPGncAGQx2+GaGArhTFrZPESyjJp7ajG0+bYWfpzZy2LYu0P60cZC0DVlw+D+rorY= X-Received: by 2002:a05:622a:1817:b0:4b1:2122:4a51 with SMTP id d75a77b69052e-4b2aaa599ebmr78900971cf.4.1756063789261; Sun, 24 Aug 2025 12:29:49 -0700 (PDT) List-Id: Commit messages for all branches of the ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-ports-all@freebsd.org Sender: owner-dev-commits-ports-all@FreeBSD.org MIME-Version: 1.0 References: <202508241925.57OJPqw1087694@gitrepo.freebsd.org> In-Reply-To: <202508241925.57OJPqw1087694@gitrepo.freebsd.org> From: Nuno Teixeira Date: Sun, 24 Aug 2025 20:29:38 +0100 X-Gmail-Original-Message-ID: X-Gm-Features: Ac12FXzGOrdQ9joy1oUV9kGe6s3AHUFuCJwQhGTkh8t0DQ-4XPT-THBGC5oiV2s Message-ID: Subject: Re: git: 2d664816a4a4 - main - audio/cmus: Fix build with FFmpeg 8 To: ports-committers@freebsd.org, dev-commits-ports-all@freebsd.org, dev-commits-ports-main@freebsd.org Content-Type: multipart/alternative; boundary="0000000000005cac46063d21764e" --0000000000005cac46063d21764e Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Forgot to include PR: 289073 ( https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D289073 ) Nuno Teixeira escreveu (domingo, 24/08/2025 =C3=A0(s) 20:25): > The branch main has been updated by eduardo: > > URL: > https://cgit.FreeBSD.org/ports/commit/?id=3D2d664816a4a4ec943cfde82270137= 44c3d3719fb > > commit 2d664816a4a4ec943cfde8227013744c3d3719fb > Author: Nuno Teixeira > AuthorDate: 2025-08-24 19:13:46 +0000 > Commit: Nuno Teixeira > CommitDate: 2025-08-24 19:19:00 +0000 > > audio/cmus: Fix build with FFmpeg 8 > > Apply upstream patch to fix build > --- > audio/cmus/files/patch-fix-ffmpeg8 | 1841 > ++++++++++++++++++++++++++++++++++++ > 1 file changed, 1841 insertions(+) > > diff --git a/audio/cmus/files/patch-fix-ffmpeg8 > b/audio/cmus/files/patch-fix-ffmpeg8 > new file mode 100644 > index 000000000000..ff1407a55467 > --- /dev/null > +++ b/audio/cmus/files/patch-fix-ffmpeg8 > @@ -0,0 +1,1841 @@ > +From 9f3b9efd8bd5508ffd069cbd0c228857ee11e1e5 Mon Sep 17 00:00:00 2001 > +From: ihy123 > +Date: Thu, 14 Aug 2025 12:44:10 +0300 > +Subject: [PATCH 01/12] ip/ffmpeg: more precise seeking > + > +av_seek_frame() and avformat_seek_file() seek to nearest "keyframe". For > +codecs like, for example, ape this means that seeking will be very off > +(5 seconds or more). So what we do is: > +1. seek to nearest "keyframe" before the desired time, > +2. discard some frames to approach the desired time. > +--- > + ip/ffmpeg.c | 154 ++++++++++++++++++++++++++++++++-------------------- > + 1 file changed, 94 insertions(+), 60 deletions(-) > + > +diff --git ip/ffmpeg.c ip/ffmpeg.c > +index 21b9a01f4..ecbf00582 100644 > +--- ip/ffmpeg.c > ++++ ip/ffmpeg.c > +@@ -44,6 +44,8 @@ struct ffmpeg_input { > + AVPacket pkt; > + int curr_pkt_size; > + uint8_t *curr_pkt_buf; > ++ int64_t seek_ts; > ++ int64_t prev_frame_end; > + int stream_index; > + > + unsigned long curr_size; > +@@ -76,6 +78,8 @@ static struct ffmpeg_input *ffmpeg_input_create(void) > + return NULL; > + } > + input->curr_pkt_size =3D 0; > ++ input->seek_ts =3D -1; > ++ input->prev_frame_end =3D -1; > + input->curr_pkt_buf =3D input->pkt.data; > + return input; > + } > +@@ -314,10 +318,7 @@ static int ffmpeg_fill_buffer(struct > input_plugin_data *ip_data, AVFormatContext > + #else > + AVFrame *frame =3D avcodec_alloc_frame(); > + #endif > +- int got_frame; > + while (1) { > +- int len; > +- > + if (input->curr_pkt_size <=3D 0) { > + #if LIBAVCODEC_VERSION_MAJOR >=3D 56 > + av_packet_unref(&input->pkt); > +@@ -333,78 +334,108 @@ static int ffmpeg_fill_buffer(struct > input_plugin_data *ip_data, AVFormatContext > + #endif > + return 0; > + } > +- if (input->pkt.stream_index =3D=3D > input->stream_index) { > +- input->curr_pkt_size =3D input->pkt.size; > +- input->curr_pkt_buf =3D input->pkt.data; > +- input->curr_size +=3D input->pkt.size; > +- input->curr_duration +=3D > input->pkt.duration; > +- } > +- continue; > +- } > + > +- { > +- AVPacket avpkt; > +- av_new_packet(&avpkt, input->curr_pkt_size); > +- memcpy(avpkt.data, input->curr_pkt_buf, > input->curr_pkt_size); > ++ if (input->pkt.stream_index !=3D input->stream_in= dex) > ++ continue; > ++ input->curr_pkt_size =3D input->pkt.size; > ++ input->curr_pkt_buf =3D input->pkt.data; > ++ input->curr_size +=3D input->pkt.size; > ++ input->curr_duration +=3D input->pkt.duration; > ++ > + #if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > +- int send_result =3D avcodec_send_packet(cc, &avpk= t); > +- if (send_result !=3D 0) { > +- if (send_result !=3D AVERROR(EAGAIN)) { > +- d_print("avcodec_send_packet() > returned %d\n", send_result); > +- char > errstr[AV_ERROR_MAX_STRING_SIZE]; > +- if (!av_strerror(send_result, > errstr, AV_ERROR_MAX_STRING_SIZE )) > +- { > +- d_print("av_strerror(): > %s\n", errstr); > +- } else { > +- d_print("av_strerror(): > Description for error cannot be found\n"); > +- } > +- av_packet_unref(&avpkt); > +- return -IP_ERROR_INTERNAL; > ++ int send_result =3D avcodec_send_packet(cc, > &input->pkt); > ++ if (send_result !=3D 0 && send_result !=3D > AVERROR(EAGAIN)) { > ++ d_print("avcodec_send_packet() returned > %d\n", send_result); > ++ char errstr[AV_ERROR_MAX_STRING_SIZE]; > ++ if (!av_strerror(send_result, errstr, > AV_ERROR_MAX_STRING_SIZE )) > ++ { > ++ d_print("av_strerror(): %s\n", > errstr); > ++ } else { > ++ d_print("av_strerror(): > Description for error cannot be found\n"); > + } > +- len =3D 0; > +- } else { > +- len =3D input->curr_pkt_size; > ++ return -IP_ERROR_INTERNAL; > + } > +- > +- int recv_result =3D avcodec_receive_frame(cc, fra= me); > +- got_frame =3D (recv_result =3D=3D 0) ? 1 : 0; > +-#else > +- len =3D avcodec_decode_audio4(cc, frame, &got_fra= me, > &avpkt); > +-#endif > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 56 > +- av_packet_unref(&avpkt); > +-#else > +- av_free_packet(&avpkt); > + #endif > + } > ++ > ++#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > ++ int recv_result =3D avcodec_receive_frame(cc, frame); > ++ if (recv_result < 0) { > ++ input->curr_pkt_size =3D 0; > ++ continue; > ++ } > ++#else > ++ int got_frame; > ++ int len =3D avcodec_decode_audio4(cc, frame, &got_frame, > &input->pkt); > + if (len < 0) { > + /* this is often reached when seeking, not sure > why */ > + input->curr_pkt_size =3D 0; > + continue; > + } > +- input->curr_pkt_size -=3D len; > +- input->curr_pkt_buf +=3D len; > +- if (got_frame) { > +- int res =3D swr_convert(swr, > +- &output->buffer, > +- frame->nb_samples, > +- (const uint8_t > **)frame->extended_data, > +- frame->nb_samples); > +- if (res < 0) > +- res =3D 0; > +- output->buffer_pos =3D output->buffer; > ++ if (!got_frame) > ++ continue; > ++#endif > ++ > ++ int64_t frame_ts =3D -1; > ++ if (frame->pts) > ++ frame_ts =3D frame->pts; > ++ else if (frame->pkt_pts) > ++ frame_ts =3D frame->pkt_pts; > ++ else if (frame->pkt_dts) > ++ frame_ts =3D frame->pkt_dts; > ++ > ++ const uint8_t **in =3D (const uint8_t > **)frame->extended_data; > ++ int in_count =3D frame->nb_samples; > ++ if (input->seek_ts > 0 && (frame_ts >=3D 0 || > input->prev_frame_end >=3D 0)) { > ++ struct ffmpeg_private *priv =3D ip_data->private; > ++ AVStream *st =3D > priv->input_context->streams[priv->input->stream_index]; > ++ if (frame_ts >=3D 0) > ++ frame_ts =3D av_rescale_q(frame_ts, > st->time_base, AV_TIME_BASE_Q); > ++ else > ++ frame_ts =3D input->prev_frame_end; > ++ int64_t frame_dur =3D av_rescale(frame->nb_sample= s, > AV_TIME_BASE, sf_get_rate(ip_data->sf)); > ++ int64_t frame_end =3D frame_ts + frame_dur; > ++ input->prev_frame_end =3D frame_end; > ++ d_print("seek_ts: %ld, frame_ts: %ld, frame_end: > %ld\n", input->seek_ts, frame_ts, frame_end); > ++ if (frame_end <=3D input->seek_ts) > ++ continue; > ++ > ++ /* skip part of this frame */ > ++ int64_t skip_samples =3D av_rescale(input->seek_t= s - > frame_ts, sf_get_rate(ip_data->sf), AV_TIME_BASE); > ++ in_count -=3D skip_samples; > ++ if (av_sample_fmt_is_planar(frame->format)) { > ++ for (int i =3D 0; i < cc->channels; i++) = { > ++ in[i] +=3D skip_samples * > sf_get_sample_size(ip_data->sf); > ++ } > ++ } else { > ++ *in +=3D skip_samples * cc->channels * > sf_get_sample_size(ip_data->sf); > ++ } > ++ > ++ input->seek_ts =3D -1; > ++ input->prev_frame_end =3D -1; > ++ } > ++ > ++ int res =3D swr_convert(swr, > ++ &output->buffer, > ++ frame->nb_samples, > ++ in, > ++ in_count); > ++ if (res < 0) > ++ res =3D 0; > ++ > ++ output->buffer_pos =3D output->buffer; > + #if LIBAVCODEC_VERSION_MAJOR >=3D 60 > +- output->buffer_used_len =3D res * > cc->ch_layout.nb_channels * sf_get_sample_size(ip_data->sf); > ++ output->buffer_used_len =3D res * cc->ch_layout.nb_channe= ls > * sf_get_sample_size(ip_data->sf); > + #else > +- output->buffer_used_len =3D res * cc->channels * > sf_get_sample_size(ip_data->sf); > ++ output->buffer_used_len =3D res * cc->channels * > sf_get_sample_size(ip_data->sf); > + #endif > ++ > + #if LIBAVCODEC_VERSION_MAJOR >=3D 56 > +- av_frame_free(&frame); > ++ av_frame_free(&frame); > + #else > +- avcodec_free_frame(&frame); > ++ avcodec_free_frame(&frame); > + #endif > +- return output->buffer_used_len; > +- } > ++ return output->buffer_used_len; > + } > + /* This should never get here. */ > + return -IP_ERROR_INTERNAL; > +@@ -437,13 +468,16 @@ static int ffmpeg_seek(struct input_plugin_data > *ip_data, double offset) > + AVStream *st =3D > priv->input_context->streams[priv->input->stream_index]; > + int ret; > + > +- int64_t pts =3D av_rescale_q(offset * AV_TIME_BASE, AV_TIME_BASE_= Q, > st->time_base); > ++ priv->input->seek_ts =3D offset * AV_TIME_BASE; > ++ priv->input->prev_frame_end =3D -1; > ++ int64_t ts =3D av_rescale(offset, st->time_base.den, > st->time_base.num); > + > + avcodec_flush_buffers(priv->codec_context); > + /* Force reading a new packet in next ffmpeg_fill_buffer(). */ > + priv->input->curr_pkt_size =3D 0; > + > +- ret =3D av_seek_frame(priv->input_context, > priv->input->stream_index, pts, 0); > ++ ret =3D avformat_seek_file(priv->input_context, > ++ priv->input->stream_index, 0, ts, ts, 0); > + > + if (ret < 0) { > + return -IP_ERROR_FUNCTION_NOT_SUPPORTED; > + > +From ec84fa7b4b4a72c19e2ab04eac864c99df6d2e4e Mon Sep 17 00:00:00 2001 > +From: ihy123 > +Date: Fri, 15 Aug 2025 21:42:19 +0300 > +Subject: [PATCH 02/12] ip/ffmpeg: skip samples only when needed > + > +--- > + ip/ffmpeg.c | 32 ++++++++++++++++++-------------- > + 1 file changed, 18 insertions(+), 14 deletions(-) > + > +diff --git ip/ffmpeg.c ip/ffmpeg.c > +index ecbf00582..5f5a4f37b 100644 > +--- ip/ffmpeg.c > ++++ ip/ffmpeg.c > +@@ -393,22 +393,26 @@ static int ffmpeg_fill_buffer(struct > input_plugin_data *ip_data, AVFormatContext > + frame_ts =3D av_rescale_q(frame_ts, > st->time_base, AV_TIME_BASE_Q); > + else > + frame_ts =3D input->prev_frame_end; > +- int64_t frame_dur =3D av_rescale(frame->nb_sample= s, > AV_TIME_BASE, sf_get_rate(ip_data->sf)); > +- int64_t frame_end =3D frame_ts + frame_dur; > +- input->prev_frame_end =3D frame_end; > +- d_print("seek_ts: %ld, frame_ts: %ld, frame_end: > %ld\n", input->seek_ts, frame_ts, frame_end); > +- if (frame_end <=3D input->seek_ts) > +- continue; > + > +- /* skip part of this frame */ > +- int64_t skip_samples =3D av_rescale(input->seek_t= s - > frame_ts, sf_get_rate(ip_data->sf), AV_TIME_BASE); > +- in_count -=3D skip_samples; > +- if (av_sample_fmt_is_planar(frame->format)) { > +- for (int i =3D 0; i < cc->channels; i++) = { > +- in[i] +=3D skip_samples * > sf_get_sample_size(ip_data->sf); > ++ if (frame_ts < input->seek_ts) { > ++ int64_t frame_dur =3D > av_rescale(frame->nb_samples, AV_TIME_BASE, sf_get_rate(ip_data->sf)); > ++ int64_t frame_end =3D frame_ts + frame_du= r; > ++ input->prev_frame_end =3D frame_end; > ++ d_print("seek_ts: %ld, frame_ts: %ld, > frame_end: %ld\n", input->seek_ts, frame_ts, frame_end); > ++ if (frame_end <=3D input->seek_ts) > ++ continue; > ++ > ++ /* skip part of this frame */ > ++ int64_t skip_samples =3D > av_rescale(input->seek_ts - frame_ts, sf_get_rate(ip_data->sf), > AV_TIME_BASE); > ++ in_count -=3D skip_samples; > ++ if > (av_sample_fmt_is_planar(frame->format)) { > ++ for (int i =3D 0; i < cc->channel= s; > i++) { > ++ in[i] +=3D skip_samples * > sf_get_sample_size(ip_data->sf); > ++ } > ++ } else { > ++ *in +=3D skip_samples * cc->chann= els > * sf_get_sample_size(ip_data->sf); > + } > +- } else { > +- *in +=3D skip_samples * cc->channels * > sf_get_sample_size(ip_data->sf); > ++ d_print("skipping %ld samples\n", > skip_samples); > + } > + > + input->seek_ts =3D -1; > + > +From 70a8761fc1d30bfa302332d0807b89c3776d3f31 Mon Sep 17 00:00:00 2001 > +From: ihy123 > +Date: Sat, 16 Aug 2025 02:43:55 +0300 > +Subject: [PATCH 03/12] ip/ffmpeg: remove excessive version checks > + > +ffmpeg download page states that v4.0.6 has > +- libavutil 56.14.100 > +- libavcodec 58.18.100 > +- libavformat 58.12.100 > +(https://ffmpeg.org/olddownload.html) > + > +After removing all checks for versions lower than these, the plugin > +still compiles with v3.3.9 headers. > + > +After all, why be better with compatibility than developers themselves? > +--- > + ip/ffmpeg.c | 109 +++++++++++----------------------------------------- > + 1 file changed, 23 insertions(+), 86 deletions(-) > + > +diff --git ip/ffmpeg.c ip/ffmpeg.c > +index 5f5a4f37b..f6a11f450 100644 > +--- ip/ffmpeg.c > ++++ ip/ffmpeg.c > +@@ -25,7 +25,6 @@ > + #include "../config/ffmpeg.h" > + #endif > + > +-#include > + #include > + #include > + #include > +@@ -43,7 +42,6 @@ > + struct ffmpeg_input { > + AVPacket pkt; > + int curr_pkt_size; > +- uint8_t *curr_pkt_buf; > + int64_t seek_ts; > + int64_t prev_frame_end; > + int stream_index; > +@@ -80,17 +78,12 @@ static struct ffmpeg_input *ffmpeg_input_create(void= ) > + input->curr_pkt_size =3D 0; > + input->seek_ts =3D -1; > + input->prev_frame_end =3D -1; > +- input->curr_pkt_buf =3D input->pkt.data; > + return input; > + } > + > + static void ffmpeg_input_free(struct ffmpeg_input *input) > + { > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 56 > + av_packet_unref(&input->pkt); > +-#else > +- av_free_packet(&input->pkt); > +-#endif > + free(input); > + } > + > +@@ -132,7 +125,7 @@ static void ffmpeg_init(void) > + > + av_log_set_level(AV_LOG_QUIET); > + > +-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 18, 100) > ++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100) > + /* We could register decoders explicitly to save memory, but we > have to > + * be careful about compatibility. */ > + av_register_all(); > +@@ -149,9 +142,7 @@ static int ffmpeg_open(struct input_plugin_data > *ip_data) > + AVCodec const *codec; > + AVCodecContext *cc =3D NULL; > + AVFormatContext *ic =3D NULL; > +-#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > + AVCodecParameters *cp =3D NULL; > +-#endif > + SwrContext *swr =3D NULL; > + > + ffmpeg_init(); > +@@ -171,20 +162,11 @@ static int ffmpeg_open(struct input_plugin_data > *ip_data) > + } > + > + for (i =3D 0; i < ic->nb_streams; i++) { > +- > +-#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > + cp =3D ic->streams[i]->codecpar; > + if (cp->codec_type =3D=3D AVMEDIA_TYPE_AUDIO) { > + stream_index =3D i; > + break; > + } > +-#else > +- cc =3D ic->streams[i]->codec; > +- if (cc->codec_type =3D=3D AVMEDIA_TYPE_AUDIO) { > +- stream_index =3D i; > +- break; > +- } > +-#endif > + } > + > + if (stream_index =3D=3D -1) { > +@@ -193,13 +175,9 @@ static int ffmpeg_open(struct input_plugin_data > *ip_data) > + break; > + } > + > +-#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > + codec =3D avcodec_find_decoder(cp->codec_id); > + cc =3D avcodec_alloc_context3(codec); > + avcodec_parameters_to_context(cc, cp); > +-#else > +- codec =3D avcodec_find_decoder(cc->codec_id); > +-#endif > + if (!codec) { > + d_print("codec not found: %d, %s\n", cc->codec_id= , > avcodec_get_name(cc->codec_id)); > + err =3D -IP_ERROR_UNSUPPORTED_FILE_TYPE; > +@@ -217,9 +195,7 @@ static int ffmpeg_open(struct input_plugin_data > *ip_data) > + > + if (err < 0) { > + /* Clean up. cc is never opened at this point. (See > above assumption.) */ > +-#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > + avcodec_free_context(&cc); > +-#endif > + avformat_close_input(&ic); > + return err; > + } > +@@ -231,9 +207,7 @@ static int ffmpeg_open(struct input_plugin_data > *ip_data) > + priv->input =3D ffmpeg_input_create(); > + if (priv->input =3D=3D NULL) { > + avcodec_close(cc); > +-#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > + avcodec_free_context(&cc); > +-#endif > + avformat_close_input(&ic); > + free(priv); > + return -IP_ERROR_INTERNAL; > +@@ -244,7 +218,7 @@ static int ffmpeg_open(struct input_plugin_data > *ip_data) > + /* Prepare for resampling. */ > + out_sample_rate =3D min_u(cc->sample_rate, 384000); > + swr =3D swr_alloc(); > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 60 > ++#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(59, 24, 100) > + if (cc->ch_layout.order =3D=3D AV_CHANNEL_ORDER_UNSPEC) > + av_channel_layout_default(&cc->ch_layout, > cc->ch_layout.nb_channels); > + av_opt_set_chlayout(swr, "in_chlayout", &cc->ch_layout, 0); > +@@ -259,7 +233,7 @@ static int ffmpeg_open(struct input_plugin_data > *ip_data) > + priv->swr =3D swr; > + > + ip_data->private =3D priv; > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 60 > ++#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(59, 24, 100) > + ip_data->sf =3D sf_rate(out_sample_rate) | > sf_channels(cc->ch_layout.nb_channels); > + #else > + ip_data->sf =3D sf_rate(out_sample_rate) | sf_channels(cc->channe= ls); > +@@ -281,10 +255,12 @@ static int ffmpeg_open(struct input_plugin_data > *ip_data) > + } > + swr_init(swr); > + ip_data->sf |=3D sf_host_endian(); > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 60 > +- channel_map_init_waveex(cc->ch_layout.nb_channels, > cc->ch_layout.u.mask, ip_data->channel_map); > ++#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(59, 24, 100) > ++ channel_map_init_waveex(cc->ch_layout.nb_channels, > ++ cc->ch_layout.u.mask, ip_data->channel_map); > + #else > +- channel_map_init_waveex(cc->channels, cc->channel_layout, > ip_data->channel_map); > ++ channel_map_init_waveex(cc->channels, > ++ cc->channel_layout, ip_data->channel_map); > + #endif > + return 0; > + } > +@@ -294,9 +270,7 @@ static int ffmpeg_close(struct input_plugin_data > *ip_data) > + struct ffmpeg_private *priv =3D ip_data->private; > + > + avcodec_close(priv->codec_context); > +-#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > + avcodec_free_context(&priv->codec_context); > +-#endif > + avformat_close_input(&priv->input_context); > + swr_free(&priv->swr); > + ffmpeg_input_free(priv->input); > +@@ -310,39 +284,27 @@ static int ffmpeg_close(struct input_plugin_data > *ip_data) > + * This returns the number of bytes added to the buffer. > + * It returns < 0 on error. 0 on EOF. > + */ > +-static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, > AVFormatContext *ic, AVCodecContext *cc, > +- struct ffmpeg_input *input, struct > ffmpeg_output *output, SwrContext *swr) > ++static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, > ++ AVFormatContext *ic, AVCodecContext *cc, > ++ struct ffmpeg_input *input, struct ffmpeg_output *output, > ++ SwrContext *swr) > + { > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 56 > + AVFrame *frame =3D av_frame_alloc(); > +-#else > +- AVFrame *frame =3D avcodec_alloc_frame(); > +-#endif > + while (1) { > + if (input->curr_pkt_size <=3D 0) { > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 56 > + av_packet_unref(&input->pkt); > +-#else > +- av_free_packet(&input->pkt); > +-#endif > + if (av_read_frame(ic, &input->pkt) < 0) { > + /* Force EOF once we can read no longer. = */ > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 56 > + av_frame_free(&frame); > +-#else > +- avcodec_free_frame(&frame); > +-#endif > + return 0; > + } > + > + if (input->pkt.stream_index !=3D input->stream_in= dex) > + continue; > + input->curr_pkt_size =3D input->pkt.size; > +- input->curr_pkt_buf =3D input->pkt.data; > + input->curr_size +=3D input->pkt.size; > + input->curr_duration +=3D input->pkt.duration; > + > +-#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > + int send_result =3D avcodec_send_packet(cc, > &input->pkt); > + if (send_result !=3D 0 && send_result !=3D > AVERROR(EAGAIN)) { > + d_print("avcodec_send_packet() returned > %d\n", send_result); > +@@ -355,32 +317,17 @@ static int ffmpeg_fill_buffer(struct > input_plugin_data *ip_data, AVFormatContext > + } > + return -IP_ERROR_INTERNAL; > + } > +-#endif > + } > + > +-#if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(57, 48, 101) > + int recv_result =3D avcodec_receive_frame(cc, frame); > + if (recv_result < 0) { > + input->curr_pkt_size =3D 0; > + continue; > + } > +-#else > +- int got_frame; > +- int len =3D avcodec_decode_audio4(cc, frame, &got_frame, > &input->pkt); > +- if (len < 0) { > +- /* this is often reached when seeking, not sure > why */ > +- input->curr_pkt_size =3D 0; > +- continue; > +- } > +- if (!got_frame) > +- continue; > +-#endif > + > + int64_t frame_ts =3D -1; > + if (frame->pts) > + frame_ts =3D frame->pts; > +- else if (frame->pkt_pts) > +- frame_ts =3D frame->pkt_pts; > + else if (frame->pkt_dts) > + frame_ts =3D frame->pkt_dts; > + > +@@ -395,7 +342,7 @@ static int ffmpeg_fill_buffer(struct > input_plugin_data *ip_data, AVFormatContext > + frame_ts =3D input->prev_frame_end; > + > + if (frame_ts < input->seek_ts) { > +- int64_t frame_dur =3D > av_rescale(frame->nb_samples, AV_TIME_BASE, sf_get_rate(ip_data->sf)); > ++ int64_t frame_dur =3D > av_rescale(frame->nb_samples, AV_TIME_BASE, frame->sample_rate); > + int64_t frame_end =3D frame_ts + frame_du= r; > + input->prev_frame_end =3D frame_end; > + d_print("seek_ts: %ld, frame_ts: %ld, > frame_end: %ld\n", input->seek_ts, frame_ts, frame_end); > +@@ -403,14 +350,14 @@ static int ffmpeg_fill_buffer(struct > input_plugin_data *ip_data, AVFormatContext > + continue; > + > + /* skip part of this frame */ > +- int64_t skip_samples =3D > av_rescale(input->seek_ts - frame_ts, sf_get_rate(ip_data->sf), > AV_TIME_BASE); > ++ int64_t skip_samples =3D > av_rescale(input->seek_ts - frame_ts, frame->sample_rate, AV_TIME_BASE); > + in_count -=3D skip_samples; > + if > (av_sample_fmt_is_planar(frame->format)) { > +- for (int i =3D 0; i < cc->channel= s; > i++) { > ++ for (int i =3D 0; i < > sf_get_channels(ip_data->sf); i++) { > + in[i] +=3D skip_samples * > sf_get_sample_size(ip_data->sf); > + } > + } else { > +- *in +=3D skip_samples * cc->chann= els > * sf_get_sample_size(ip_data->sf); > ++ *in +=3D skip_samples * > sf_get_frame_size(ip_data->sf); > + } > + d_print("skipping %ld samples\n", > skip_samples); > + } > +@@ -428,17 +375,9 @@ static int ffmpeg_fill_buffer(struct > input_plugin_data *ip_data, AVFormatContext > + res =3D 0; > + > + output->buffer_pos =3D output->buffer; > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 60 > +- output->buffer_used_len =3D res * cc->ch_layout.nb_channe= ls > * sf_get_sample_size(ip_data->sf); > +-#else > +- output->buffer_used_len =3D res * cc->channels * > sf_get_sample_size(ip_data->sf); > +-#endif > ++ output->buffer_used_len =3D res * > sf_get_frame_size(ip_data->sf); > + > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 56 > + av_frame_free(&frame); > +-#else > +- avcodec_free_frame(&frame); > +-#endif > + return output->buffer_used_len; > + } > + /* This should never get here. */ > +@@ -453,11 +392,11 @@ static int ffmpeg_read(struct input_plugin_data > *ip_data, char *buffer, int coun > + int out_size; > + > + if (output->buffer_used_len =3D=3D 0) { > +- rc =3D ffmpeg_fill_buffer(ip_data, priv->input_context, > priv->codec_context, > ++ rc =3D ffmpeg_fill_buffer(ip_data, > ++ priv->input_context, priv->codec_context, > + priv->input, priv->output, priv->swr); > +- if (rc <=3D 0) { > ++ if (rc <=3D 0) > + return rc; > +- } > + } > + out_size =3D min_i(output->buffer_used_len, count); > + memcpy(buffer, output->buffer_pos, out_size); > +@@ -477,6 +416,7 @@ static int ffmpeg_seek(struct input_plugin_data > *ip_data, double offset) > + int64_t ts =3D av_rescale(offset, st->time_base.den, > st->time_base.num); > + > + avcodec_flush_buffers(priv->codec_context); > ++ /* TODO: also flush swresample buffers */ > + /* Force reading a new packet in next ffmpeg_fill_buffer(). */ > + priv->input->curr_pkt_size =3D 0; > + > +@@ -501,7 +441,8 @@ static void ffmpeg_read_metadata(struct > growing_keyvals *c, AVDictionary *metada > + } > + } > + > +-static int ffmpeg_read_comments(struct input_plugin_data *ip_data, > struct keyval **comments) > ++static int ffmpeg_read_comments(struct input_plugin_data *ip_data, > ++ struct keyval **comments) > + { > + struct ffmpeg_private *priv =3D ip_data->private; > + AVFormatContext *ic =3D priv->input_context; > +@@ -538,11 +479,7 @@ static long ffmpeg_current_bitrate(struct > input_plugin_data *ip_data) > + AVStream *st =3D > priv->input_context->streams[priv->input->stream_index]; > + long bitrate =3D -1; > + /* ape codec returns silly numbers */ > +-#if LIBAVCODEC_VERSION_MAJOR >=3D 55 > + if (priv->codec->id =3D=3D AV_CODEC_ID_APE) > +-#else > +- if (priv->codec->id =3D=3D CODEC_ID_APE) > +-#endif > + return -1; > + if (priv->input->curr_duration > 0) { > + double seconds =3D priv->input->curr_duration * > av_q2d(st->time_base); > + > +From e1a2374a60a41987f95c7d892ebc1b150df7acb1 Mon Sep 17 00:00:00 2001 > +From: ihy123 > +Date: Sun, 17 Aug 2025 04:05:36 +0300 > +Subject: [PATCH 04/12] ip/ffmpeg: major refactor > + > +--- > + ip/ffmpeg.c | 643 +++++++++++++++++++++++++++------------------------- > + 1 file changed, 330 insertions(+), 313 deletions(-) > + > +diff --git ip/ffmpeg.c ip/ffmpeg.c > +index f6a11f450..42f630ee7 100644 > +--- ip/ffmpeg.c > ++++ ip/ffmpeg.c > +@@ -35,84 +35,32 @@ > + #include > + #endif > + > +-#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE > +-#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 > +-#endif > ++struct ffmpeg_private { > ++ AVCodecContext *codec_ctx; > ++ AVFormatContext *format_ctx; > ++ AVCodec const *codec; > ++ SwrContext *swr; > ++ int stream_index; > + > +-struct ffmpeg_input { > +- AVPacket pkt; > +- int curr_pkt_size; > ++ AVPacket *pkt; > ++ AVFrame *frame; > + int64_t seek_ts; > + int64_t prev_frame_end; > +- int stream_index; > + > ++ /* A buffer to hold swr_convert()-ed samples */ > ++ AVFrame *swr_frame; > ++ int swr_frame_start; > ++ > ++ /* Bitrate estimation */ > + unsigned long curr_size; > + unsigned long curr_duration; > + }; > + > +-struct ffmpeg_output { > +- uint8_t *buffer; > +- uint8_t *buffer_malloc; > +- uint8_t *buffer_pos; /* current buffer position */ > +- int buffer_used_len; > +-}; > +- > +-struct ffmpeg_private { > +- AVCodecContext *codec_context; > +- AVFormatContext *input_context; > +- AVCodec const *codec; > +- SwrContext *swr; > +- > +- struct ffmpeg_input *input; > +- struct ffmpeg_output *output; > +-}; > +- > +-static struct ffmpeg_input *ffmpeg_input_create(void) > +-{ > +- struct ffmpeg_input *input =3D xnew(struct ffmpeg_input, 1); > +- > +- if (av_new_packet(&input->pkt, 0) !=3D 0) { > +- free(input); > +- return NULL; > +- } > +- input->curr_pkt_size =3D 0; > +- input->seek_ts =3D -1; > +- input->prev_frame_end =3D -1; > +- return input; > +-} > +- > +-static void ffmpeg_input_free(struct ffmpeg_input *input) > +-{ > +- av_packet_unref(&input->pkt); > +- free(input); > +-} > +- > +-static struct ffmpeg_output *ffmpeg_output_create(void) > +-{ > +- struct ffmpeg_output *output =3D xnew(struct ffmpeg_output, 1); > +- > +- output->buffer_malloc =3D xnew(uint8_t, AVCODEC_MAX_AUDIO_FRAME_S= IZE > + 15); > +- output->buffer =3D output->buffer_malloc; > +- /* align to 16 bytes so avcodec can SSE/Altivec/etc */ > +- while ((intptr_t) output->buffer % 16) > +- output->buffer +=3D 1; > +- output->buffer_pos =3D output->buffer; > +- output->buffer_used_len =3D 0; > +- return output; > +-} > +- > +-static void ffmpeg_output_free(struct ffmpeg_output *output) > +-{ > +- free(output->buffer_malloc); > +- output->buffer_malloc =3D NULL; > +- output->buffer =3D NULL; > +- free(output); > +-} > +- > +-static inline void ffmpeg_buffer_flush(struct ffmpeg_output *output) > ++static const char *ffmpeg_errmsg(int err) > + { > +- output->buffer_pos =3D output->buffer; > +- output->buffer_used_len =3D 0; > ++ static char errstr[AV_ERROR_MAX_STRING_SIZE]; > ++ av_strerror(err, errstr, AV_ERROR_MAX_STRING_SIZE); > ++ return errstr; > + } > + > + static void ffmpeg_init(void) > +@@ -132,303 +80,372 @@ static void ffmpeg_init(void) > + #endif > + } > + > +-static int ffmpeg_open(struct input_plugin_data *ip_data) > ++static int ffmpeg_open_input(struct input_plugin_data *ip_data, > ++ struct ffmpeg_private *priv) > + { > +- struct ffmpeg_private *priv; > +- int err =3D 0; > +- int i; > +- int stream_index =3D -1; > +- int out_sample_rate; > +- AVCodec const *codec; > +- AVCodecContext *cc =3D NULL; > + AVFormatContext *ic =3D NULL; > ++ AVCodecContext *cc =3D NULL; > + AVCodecParameters *cp =3D NULL; > +- SwrContext *swr =3D NULL; > +- > +- ffmpeg_init(); > ++ AVCodec const *codec =3D NULL; > ++ int stream_index =3D -1; > + > +- err =3D avformat_open_input(&ic, ip_data->filename, NULL, NULL); > +- if (err < 0) { > +- d_print("av_open failed: %d\n", err); > +- return -IP_ERROR_FILE_FORMAT; > ++ int err; > ++ int res =3D avformat_open_input(&ic, ip_data->filename, NULL, NUL= L); > ++ if (res < 0) { > ++ err =3D -IP_ERROR_FILE_FORMAT; > ++ goto err; > + } > + > +- do { > +- err =3D avformat_find_stream_info(ic, NULL); > +- if (err < 0) { > +- d_print("unable to find stream info: %d\n", err); > +- err =3D -IP_ERROR_FILE_FORMAT; > +- break; > +- } > +- > +- for (i =3D 0; i < ic->nb_streams; i++) { > +- cp =3D ic->streams[i]->codecpar; > +- if (cp->codec_type =3D=3D AVMEDIA_TYPE_AUDIO) { > +- stream_index =3D i; > +- break; > +- } > +- } > +- > +- if (stream_index =3D=3D -1) { > +- d_print("could not find audio stream\n"); > +- err =3D -IP_ERROR_FILE_FORMAT; > +- break; > +- } > +- > +- codec =3D avcodec_find_decoder(cp->codec_id); > +- cc =3D avcodec_alloc_context3(codec); > +- avcodec_parameters_to_context(cc, cp); > +- if (!codec) { > +- d_print("codec not found: %d, %s\n", cc->codec_id= , > avcodec_get_name(cc->codec_id)); > +- err =3D -IP_ERROR_UNSUPPORTED_FILE_TYPE; > +- break; > +- } > ++ res =3D avformat_find_stream_info(ic, NULL); > ++ if (res < 0) { > ++ d_print("unable to find stream info\n"); > ++ err =3D -IP_ERROR_FILE_FORMAT; > ++ goto err; > ++ } > + > +- if (avcodec_open2(cc, codec, NULL) < 0) { > +- d_print("could not open codec: %d, %s\n", > cc->codec_id, avcodec_get_name(cc->codec_id)); > +- err =3D -IP_ERROR_UNSUPPORTED_FILE_TYPE; > ++ for (int i =3D 0; i < ic->nb_streams; i++) { > ++ cp =3D ic->streams[i]->codecpar; > ++ if (cp->codec_type =3D=3D AVMEDIA_TYPE_AUDIO) { > ++ stream_index =3D i; > + break; > + } > ++ } > + > +- /* We assume below that no more errors follow. */ > +- } while (0); > ++ if (stream_index =3D=3D -1) { > ++ d_print("could not find audio stream\n"); > ++ err =3D -IP_ERROR_FILE_FORMAT; > ++ goto err_silent; > ++ } > + > +- if (err < 0) { > +- /* Clean up. cc is never opened at this point. (See > above assumption.) */ > +- avcodec_free_context(&cc); > +- avformat_close_input(&ic); > +- return err; > ++ codec =3D avcodec_find_decoder(cp->codec_id); > ++ if (!codec) { > ++ d_print("codec (id: %d, name: %s) not found\n", > ++ cc->codec_id, > avcodec_get_name(cc->codec_id)); > ++ err =3D -IP_ERROR_UNSUPPORTED_FILE_TYPE; > ++ goto err_silent; > ++ } > ++ cc =3D avcodec_alloc_context3(codec); > ++ avcodec_parameters_to_context(cc, cp); > ++ > ++ res =3D avcodec_open2(cc, codec, NULL); > ++ if (res < 0) { > ++ d_print("could not open codec (id: %d, name: %s)\n", > ++ cc->codec_id, > avcodec_get_name(cc->codec_id)); > ++ err =3D -IP_ERROR_UNSUPPORTED_FILE_TYPE; > ++ goto err; > + } > + > +- priv =3D xnew(struct ffmpeg_private, 1); > +- priv->codec_context =3D cc; > +- priv->input_context =3D ic; > ++ priv->format_ctx =3D ic; > ++ priv->codec_ctx =3D cc; > + priv->codec =3D codec; > +- priv->input =3D ffmpeg_input_create(); > +- if (priv->input =3D=3D NULL) { > +- avcodec_close(cc); > +- avcodec_free_context(&cc); > +- avformat_close_input(&ic); > +- free(priv); > +- return -IP_ERROR_INTERNAL; > ++ priv->stream_index =3D stream_index; > ++ return 0; > ++err: > ++ d_print("%s\n", ffmpeg_errmsg(res)); > ++err_silent: > ++ avcodec_free_context(&cc); > ++ avformat_close_input(&ic); > ++ return err; > ++} > ++ > ++static void ffmpeg_set_sf_and_swr_opts(SwrContext *swr, AVCodecContext > *cc, > ++ sample_format_t *sf_out, enum AVSampleFormat > *out_sample_fmt) > ++{ > ++ int out_sample_rate =3D min_u(cc->sample_rate, 384000); > ++ sample_format_t sf =3D sf_rate(out_sample_rate) | sf_host_endian(= ); > ++ av_opt_set_int(swr, "in_sample_rate", cc->sample_rate, 0); > ++ av_opt_set_int(swr, "out_sample_rate", out_sample_rate, 0); > ++ > ++ *out_sample_fmt =3D cc->sample_fmt; > ++ switch (*out_sample_fmt) { > ++ case AV_SAMPLE_FMT_U8: > ++ sf |=3D sf_bits(8) | sf_signed(0); > ++ break; > ++ case AV_SAMPLE_FMT_S32: > ++ sf |=3D sf_bits(32) | sf_signed(1); > ++ break; > ++ default: > ++ sf |=3D sf_bits(16) | sf_signed(1); > ++ *out_sample_fmt =3D AV_SAMPLE_FMT_S16; > + } > +- priv->input->stream_index =3D stream_index; > +- priv->output =3D ffmpeg_output_create(); > ++ av_opt_set_sample_fmt(swr, "in_sample_fmt", cc->sample_fmt, 0); > ++ av_opt_set_sample_fmt(swr, "out_sample_fmt", *out_sample_fmt, 0); > + > +- /* Prepare for resampling. */ > +- out_sample_rate =3D min_u(cc->sample_rate, 384000); > +- swr =3D swr_alloc(); > + #if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(59, 24, 100) > ++ sf |=3D sf_channels(cc->ch_layout.nb_channels); > ++ > + if (cc->ch_layout.order =3D=3D AV_CHANNEL_ORDER_UNSPEC) > + av_channel_layout_default(&cc->ch_layout, > cc->ch_layout.nb_channels); > +- av_opt_set_chlayout(swr, "in_chlayout", &cc->ch_layout, 0); > +- av_opt_set_chlayout(swr, "out_chlayout", &cc->ch_layout, 0); > ++ av_opt_set_chlayout(swr, "in_chlayout", &cc->ch_layout, 0); > ++ av_opt_set_chlayout(swr, "out_chlayout", &cc->ch_layout, 0); > + #else > +- av_opt_set_int(swr, "in_channel_layout", > av_get_default_channel_layout(cc->channels), 0); > +- av_opt_set_int(swr, "out_channel_layout", > av_get_default_channel_layout(cc->channels), 0); > ++ sf |=3D sf_channels(cc->channels); > ++ > ++ av_opt_set_int(swr, "in_channel_layout", > ++ av_get_default_channel_layout(cc->channels), 0); > ++ av_opt_set_int(swr, "out_channel_layout", > ++ av_get_default_channel_layout(cc->channels), 0); > + #endif > +- av_opt_set_int(swr, "in_sample_rate", cc->sample_rate, 0); > +- av_opt_set_int(swr, "out_sample_rate", out_sample_rate, 0); > +- av_opt_set_sample_fmt(swr, "in_sample_fmt", cc->sample_fmt, 0); > +- priv->swr =3D swr; > + > +- ip_data->private =3D priv; > ++ *sf_out =3D sf; > ++} > ++ > ++static int ffmpeg_init_swr_frame(struct ffmpeg_private *priv, > ++ sample_format_t sf, enum AVSampleFormat out_sample_fmt) > ++{ > ++ AVCodecContext *cc =3D priv->codec_ctx; > ++ AVFrame *frame =3D av_frame_alloc(); > ++ > + #if LIBAVCODEC_VERSION_INT >=3D AV_VERSION_INT(59, 24, 100) > +- ip_data->sf =3D sf_rate(out_sample_rate) | > sf_channels(cc->ch_layout.nb_channels); > ++ av_channel_layout_copy(&frame->ch_layout, &cc->ch_layout); > + #else > +- ip_data->sf =3D sf_rate(out_sample_rate) | sf_channels(cc->channe= ls); > ++ frame->channel_layout =3D > av_get_default_channel_layout(cc->channels); > + #endif > +- switch (cc->sample_fmt) { > +- case AV_SAMPLE_FMT_U8: > +- ip_data->sf |=3D sf_bits(8) | sf_signed(0); > +- av_opt_set_sample_fmt(swr, "out_sample_fmt", > AV_SAMPLE_FMT_U8, 0); > +- break; > +- case AV_SAMPLE_FMT_S32: > +- ip_data->sf |=3D sf_bits(32) | sf_signed(1); > +- av_opt_set_sample_fmt(swr, "out_sample_fmt", > AV_SAMPLE_FMT_S32, 0); > +- break; > +- /* AV_SAMPLE_FMT_S16 */ > +- default: > +- ip_data->sf |=3D sf_bits(16) | sf_signed(1); > *** 878 LINES SKIPPED *** > --=20 Nuno Teixeira FreeBSD UNIX: Web: https://FreeBSD.org --0000000000005cac46063d21764e Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+Rm9yZ290IHRvIGluY2x1ZGUgUFI6IDI4OTA3MyAowqA8YSBocmVmPSJo dHRwczovL2J1Z3MuZnJlZWJzZC5vcmcvYnVnemlsbGEvc2hvd19idWcuY2dpP2lkPTI4OTA3MyI+ aHR0cHM6Ly9idWdzLmZyZWVic2Qub3JnL2J1Z3ppbGxhL3Nob3dfYnVnLmNnaT9pZD0yODkwNzM8 L2E+wqApPC9kaXY+PGJyPjxkaXYgY2xhc3M9ImdtYWlsX3F1b3RlIGdtYWlsX3F1b3RlX2NvbnRh aW5lciI+PGRpdiBkaXI9Imx0ciIgY2xhc3M9ImdtYWlsX2F0dHIiPk51bm8gVGVpeGVpcmEgJmx0 OzxhIGhyZWY9Im1haWx0bzplZHVhcmRvQGZyZWVic2Qub3JnIj5lZHVhcmRvQGZyZWVic2Qub3Jn PC9hPiZndDsgZXNjcmV2ZXUgKGRvbWluZ28sIDI0LzA4LzIwMjUgw6AocykgMjA6MjUpOjxicj48 L2Rpdj48YmxvY2txdW90ZSBjbGFzcz0iZ21haWxfcXVvdGUiIHN0eWxlPSJtYXJnaW46MHB4IDBw eCAwcHggMC44ZXg7Ym9yZGVyLWxlZnQ6MXB4IHNvbGlkIHJnYigyMDQsMjA0LDIwNCk7cGFkZGlu Zy1sZWZ0OjFleCI+VGhlIGJyYW5jaCBtYWluIGhhcyBiZWVuIHVwZGF0ZWQgYnkgZWR1YXJkbzo8 YnI+DQo8YnI+DQpVUkw6IDxhIGhyZWY9Imh0dHBzOi8vY2dpdC5GcmVlQlNELm9yZy9wb3J0cy9j b21taXQvP2lkPTJkNjY0ODE2YTRhNGVjOTQzY2ZkZTgyMjcwMTM3NDRjM2QzNzE5ZmIiIHJlbD0i bm9yZWZlcnJlciIgdGFyZ2V0PSJfYmxhbmsiPmh0dHBzOi8vY2dpdC5GcmVlQlNELm9yZy9wb3J0 cy9jb21taXQvP2lkPTJkNjY0ODE2YTRhNGVjOTQzY2ZkZTgyMjcwMTM3NDRjM2QzNzE5ZmI8L2E+ PGJyPg0KPGJyPg0KY29tbWl0IDJkNjY0ODE2YTRhNGVjOTQzY2ZkZTgyMjcwMTM3NDRjM2QzNzE5 ZmI8YnI+DQpBdXRob3I6wqAgwqAgwqBOdW5vIFRlaXhlaXJhICZsdDtlZHVhcmRvQEZyZWVCU0Qu b3JnJmd0Ozxicj4NCkF1dGhvckRhdGU6IDIwMjUtMDgtMjQgMTk6MTM6NDYgKzAwMDA8YnI+DQpD b21taXQ6wqAgwqAgwqBOdW5vIFRlaXhlaXJhICZsdDtlZHVhcmRvQEZyZWVCU0Qub3JnJmd0Ozxi cj4NCkNvbW1pdERhdGU6IDIwMjUtMDgtMjQgMTk6MTk6MDAgKzAwMDA8YnI+DQo8YnI+DQrCoCDC oCBhdWRpby9jbXVzOiBGaXggYnVpbGQgd2l0aCBGRm1wZWcgODxicj4NCjxicj4NCsKgIMKgIEFw cGx5IHVwc3RyZWFtIHBhdGNoIHRvIGZpeCBidWlsZDxicj4NCi0tLTxicj4NCsKgYXVkaW8vY211 cy9maWxlcy9wYXRjaC1maXgtZmZtcGVnOCB8IDE4NDEgKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrPGJyPg0KwqAxIGZpbGUgY2hhbmdlZCwgMTg0MSBpbnNlcnRpb25zKCspPGJy Pg0KPGJyPg0KZGlmZiAtLWdpdCBhL2F1ZGlvL2NtdXMvZmlsZXMvcGF0Y2gtZml4LWZmbXBlZzgg Yi9hdWRpby9jbXVzL2ZpbGVzL3BhdGNoLWZpeC1mZm1wZWc4PGJyPg0KbmV3IGZpbGUgbW9kZSAx MDA2NDQ8YnI+DQppbmRleCAwMDAwMDAwMDAwMDAuLmZmMTQwN2E1NTQ2Nzxicj4NCi0tLSAvZGV2 L251bGw8YnI+DQorKysgYi9hdWRpby9jbXVzL2ZpbGVzL3BhdGNoLWZpeC1mZm1wZWc4PGJyPg0K QEAgLTAsMCArMSwxODQxIEBAPGJyPg0KK0Zyb20gOWYzYjllZmQ4YmQ1NTA4ZmZkMDY5Y2JkMGMy Mjg4NTdlZTExZTFlNSBNb24gU2VwIDE3IDAwOjAwOjAwIDIwMDE8YnI+DQorRnJvbTogaWh5MTIz ICZsdDs8YSBocmVmPSJtYWlsdG86YWxhZGluYW5kcmV5eUBnbWFpbC5jb20iIHRhcmdldD0iX2Js YW5rIj5hbGFkaW5hbmRyZXl5QGdtYWlsLmNvbTwvYT4mZ3Q7PGJyPg0KK0RhdGU6IFRodSwgMTQg QXVnIDIwMjUgMTI6NDQ6MTAgKzAzMDA8YnI+DQorU3ViamVjdDogW1BBVENIIDAxLzEyXSBpcC9m Zm1wZWc6IG1vcmUgcHJlY2lzZSBzZWVraW5nPGJyPg0KKzxicj4NCithdl9zZWVrX2ZyYW1lKCkg YW5kIGF2Zm9ybWF0X3NlZWtfZmlsZSgpIHNlZWsgdG8gbmVhcmVzdCAmcXVvdDtrZXlmcmFtZSZx dW90Oy4gRm9yPGJyPg0KK2NvZGVjcyBsaWtlLCBmb3IgZXhhbXBsZSwgYXBlIHRoaXMgbWVhbnMg dGhhdCBzZWVraW5nIHdpbGwgYmUgdmVyeSBvZmY8YnI+DQorKDUgc2Vjb25kcyBvciBtb3JlKS4g U28gd2hhdCB3ZSBkbyBpczo8YnI+DQorMS4gc2VlayB0byBuZWFyZXN0ICZxdW90O2tleWZyYW1l JnF1b3Q7IGJlZm9yZSB0aGUgZGVzaXJlZCB0aW1lLDxicj4NCisyLiBkaXNjYXJkIHNvbWUgZnJh bWVzIHRvIGFwcHJvYWNoIHRoZSBkZXNpcmVkIHRpbWUuPGJyPg0KKy0tLTxicj4NCisgaXAvZmZt cGVnLmMgfCAxNTQgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0t LS0tLS0tLTxicj4NCisgMSBmaWxlIGNoYW5nZWQsIDk0IGluc2VydGlvbnMoKyksIDYwIGRlbGV0 aW9ucygtKTxicj4NCis8YnI+DQorZGlmZiAtLWdpdMKgIGlwL2ZmbXBlZy5jwqAgaXAvZmZtcGVn LmM8YnI+DQoraW5kZXggMjFiOWEwMWY0Li5lY2JmMDA1ODIgMTAwNjQ0PGJyPg0KKy0tLcKgIGlw L2ZmbXBlZy5jPGJyPg0KKysrK8KgIGlwL2ZmbXBlZy5jPGJyPg0KK0BAIC00NCw2ICs0NCw4IEBA IHN0cnVjdCBmZm1wZWdfaW5wdXQgezxicj4NCivCoCDCoCDCoCDCoEFWUGFja2V0IHBrdDs8YnI+ DQorwqAgwqAgwqAgwqBpbnQgY3Vycl9wa3Rfc2l6ZTs8YnI+DQorwqAgwqAgwqAgwqB1aW50OF90 ICpjdXJyX3BrdF9idWY7PGJyPg0KKyvCoCDCoCDCoCBpbnQ2NF90IHNlZWtfdHM7PGJyPg0KKyvC oCDCoCDCoCBpbnQ2NF90IHByZXZfZnJhbWVfZW5kOzxicj4NCivCoCDCoCDCoCDCoGludCBzdHJl YW1faW5kZXg7PGJyPg0KKyA8YnI+DQorwqAgwqAgwqAgwqB1bnNpZ25lZCBsb25nIGN1cnJfc2l6 ZTs8YnI+DQorQEAgLTc2LDYgKzc4LDggQEAgc3RhdGljIHN0cnVjdCBmZm1wZWdfaW5wdXQgKmZm bXBlZ19pbnB1dF9jcmVhdGUodm9pZCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1 cm4gTlVMTDs8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKgIMKgaW5wdXQtJmd0O2N1 cnJfcGt0X3NpemUgPSAwOzxicj4NCisrwqAgwqAgwqAgaW5wdXQtJmd0O3NlZWtfdHMgPSAtMTs8 YnI+DQorK8KgIMKgIMKgIGlucHV0LSZndDtwcmV2X2ZyYW1lX2VuZCA9IC0xOzxicj4NCivCoCDC oCDCoCDCoGlucHV0LSZndDtjdXJyX3BrdF9idWYgPSBpbnB1dC0mZ3Q7cGt0LmRhdGE7PGJyPg0K K8KgIMKgIMKgIMKgcmV0dXJuIGlucHV0Ozxicj4NCisgfTxicj4NCitAQCAtMzE0LDEwICszMTgs NyBAQCBzdGF0aWMgaW50IGZmbXBlZ19maWxsX2J1ZmZlcihzdHJ1Y3QgaW5wdXRfcGx1Z2luX2Rh dGEgKmlwX2RhdGEsIEFWRm9ybWF0Q29udGV4dDxicj4NCisgI2Vsc2U8YnI+DQorwqAgwqAgwqAg wqBBVkZyYW1lICpmcmFtZSA9IGF2Y29kZWNfYWxsb2NfZnJhbWUoKTs8YnI+DQorICNlbmRpZjxi cj4NCistwqAgwqAgwqAgaW50IGdvdF9mcmFtZTs8YnI+DQorwqAgwqAgwqAgwqB3aGlsZSAoMSkg ezxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW50IGxlbjs8YnI+DQorLTxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoGlmIChpbnB1dC0mZ3Q7Y3Vycl9wa3Rfc2l6ZSAmbHQ7PSAwKSB7 PGJyPg0KKyAjaWYgTElCQVZDT0RFQ19WRVJTSU9OX01BSk9SICZndDs9IDU2PGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYXZfcGFja2V0X3VucmVmKCZhbXA7aW5wdXQt Jmd0O3BrdCk7PGJyPg0KK0BAIC0zMzMsNzggKzMzNCwxMDggQEAgc3RhdGljIGludCBmZm1wZWdf ZmlsbF9idWZmZXIoc3RydWN0IGlucHV0X3BsdWdpbl9kYXRhICppcF9kYXRhLCBBVkZvcm1hdENv bnRleHQ8YnI+DQorICNlbmRpZjxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoHJldHVybiAwOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoH08YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChp bnB1dC0mZ3Q7cGt0LnN0cmVhbV9pbmRleCA9PSBpbnB1dC0mZ3Q7c3RyZWFtX2luZGV4KSB7PGJy Pg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpbnB1dC0m Z3Q7Y3Vycl9wa3Rfc2l6ZSA9IGlucHV0LSZndDtwa3Quc2l6ZTs8YnI+DQorLcKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlucHV0LSZndDtjdXJyX3BrdF9idWYg PSBpbnB1dC0mZ3Q7cGt0LmRhdGE7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBpbnB1dC0mZ3Q7Y3Vycl9zaXplICs9IGlucHV0LSZndDtwa3Quc2l6 ZTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlu cHV0LSZndDtjdXJyX2R1cmF0aW9uICs9IGlucHV0LSZndDtwa3QuZHVyYXRpb247PGJyPg0KKy3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBjb250aW51ZTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIH08 YnI+DQorIDxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgezxicj4NCistwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgQVZQYWNrZXQgYXZwa3Q7PGJyPg0KKy3CoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCBhdl9uZXdfcGFja2V0KCZhbXA7YXZwa3QsIGlucHV0LSZndDtj dXJyX3BrdF9zaXplKTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIG1l bWNweShhdnBrdC5kYXRhLCBpbnB1dC0mZ3Q7Y3Vycl9wa3RfYnVmLCBpbnB1dC0mZ3Q7Y3Vycl9w a3Rfc2l6ZSk7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoaW5w dXQtJmd0O3BrdC5zdHJlYW1faW5kZXggIT0gaW5wdXQtJmd0O3N0cmVhbV9pbmRleCk8YnI+DQor K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNvbnRpbnVlOzxi cj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW5wdXQtJmd0O2N1cnJfcGt0 X3NpemUgPSBpbnB1dC0mZ3Q7cGt0LnNpemU7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBpbnB1dC0mZ3Q7Y3Vycl9wa3RfYnVmID0gaW5wdXQtJmd0O3BrdC5kYXRhOzxi cj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW5wdXQtJmd0O2N1cnJfc2l6 ZSArPSBpbnB1dC0mZ3Q7cGt0LnNpemU7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCBpbnB1dC0mZ3Q7Y3Vycl9kdXJhdGlvbiArPSBpbnB1dC0mZ3Q7cGt0LmR1cmF0aW9u Ozxicj4NCisrPGJyPg0KKyAjaWYgTElCQVZDT0RFQ19WRVJTSU9OX0lOVCAmZ3Q7PSBBVl9WRVJT SU9OX0lOVCg1NywgNDgsIDEwMSk8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIGludCBzZW5kX3Jlc3VsdCA9IGF2Y29kZWNfc2VuZF9wYWNrZXQoY2MsICZhbXA7YXZwa3Qp Ozxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHNlbmRfcmVzdWx0 ICE9IDApIHs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIGlmIChzZW5kX3Jlc3VsdCAhPSBBVkVSUk9SKEVBR0FJTikpIHs8YnI+DQorLcKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGRfcHJpbnQo JnF1b3Q7YXZjb2RlY19zZW5kX3BhY2tldCgpIHJldHVybmVkICVkXG4mcXVvdDssIHNlbmRfcmVz dWx0KTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIGNoYXIgZXJyc3RyW0FWX0VSUk9SX01BWF9TVFJJTkdfU0laRV07PGJyPg0K Ky3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCBpZiAoIWF2X3N0cmVycm9yKHNlbmRfcmVzdWx0LCBlcnJzdHIsIEFWX0VSUk9SX01BWF9TVFJJ TkdfU0laRSApKTxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgezxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZF9wcmludCgmcXVvdDthdl9z dHJlcnJvcigpOiAlc1xuJnF1b3Q7LCBlcnJzdHIpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfSBlbHNlIHs8YnI+DQorLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIGRfcHJpbnQoJnF1b3Q7YXZfc3RyZXJyb3IoKTogRGVzY3JpcHRpb24gZm9yIGVy cm9yIGNhbm5vdCBiZSBmb3VuZFxuJnF1b3Q7KTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQorLcKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGF2X3BhY2tldF91 bnJlZigmYW1wO2F2cGt0KTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHJldHVybiAtSVBfRVJST1JfSU5URVJOQUw7PGJyPg0K KyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpbnQgc2VuZF9yZXN1bHQgPSBhdmNv ZGVjX3NlbmRfcGFja2V0KGNjLCAmYW1wO2lucHV0LSZndDtwa3QpOzxicj4NCisrwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHNlbmRfcmVzdWx0ICE9IDAgJmFtcDsmYW1wOyBz ZW5kX3Jlc3VsdCAhPSBBVkVSUk9SKEVBR0FJTikpIHs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGRfcHJpbnQoJnF1b3Q7YXZjb2RlY19zZW5kX3Bh Y2tldCgpIHJldHVybmVkICVkXG4mcXVvdDssIHNlbmRfcmVzdWx0KTs8YnI+DQorK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNoYXIgZXJyc3RyW0FWX0VSUk9S X01BWF9TVFJJTkdfU0laRV07PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCBpZiAoIWF2X3N0cmVycm9yKHNlbmRfcmVzdWx0LCBlcnJzdHIsIEFWX0VS Uk9SX01BWF9TVFJJTkdfU0laRSApKTxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgezxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZF9wcmludCgmcXVvdDthdl9zdHJlcnJvcigpOiAl c1xuJnF1b3Q7LCBlcnJzdHIpOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgfSBlbHNlIHs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGRfcHJpbnQoJnF1b3Q7YXZfc3RyZXJyb3Io KTogRGVzY3JpcHRpb24gZm9yIGVycm9yIGNhbm5vdCBiZSBmb3VuZFxuJnF1b3Q7KTs8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KKy3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBsZW4gPSAwOzxicj4N CistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfSBlbHNlIHs8YnI+DQorLcKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGxlbiA9IGlucHV0LSZndDtj dXJyX3BrdF9zaXplOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgcmV0dXJuIC1JUF9FUlJPUl9JTlRFUk5BTDs8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KKy08YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIGludCByZWN2X3Jlc3VsdCA9IGF2Y29kZWNfcmVjZWl2ZV9mcmFtZShjYywg ZnJhbWUpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZ290X2ZyYW1l ID0gKHJlY3ZfcmVzdWx0ID09IDApID8gMSA6IDA7PGJyPg0KKy0jZWxzZTxicj4NCistwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgbGVuID0gYXZjb2RlY19kZWNvZGVfYXVkaW80KGNj LCBmcmFtZSwgJmFtcDtnb3RfZnJhbWUsICZhbXA7YXZwa3QpOzxicj4NCistI2VuZGlmPGJyPg0K Ky0jaWYgTElCQVZDT0RFQ19WRVJTSU9OX01BSk9SICZndDs9IDU2PGJyPg0KKy3CoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBhdl9wYWNrZXRfdW5yZWYoJmFtcDthdnBrdCk7PGJyPg0K Ky0jZWxzZTxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYXZfZnJlZV9w YWNrZXQoJmFtcDthdnBrdCk7PGJyPg0KKyAjZW5kaWY8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqB9PGJyPg0KKys8YnI+DQorKyNpZiBMSUJBVkNPREVDX1ZFUlNJT05fSU5UICZndDs9IEFW X1ZFUlNJT05fSU5UKDU3LCA0OCwgMTAxKTxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW50 IHJlY3ZfcmVzdWx0ID0gYXZjb2RlY19yZWNlaXZlX2ZyYW1lKGNjLCBmcmFtZSk7PGJyPg0KKyvC oCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAocmVjdl9yZXN1bHQgJmx0OyAwKSB7PGJyPg0KKyvCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpbnB1dC0mZ3Q7Y3Vycl9wa3Rfc2l6ZSA9IDA7 PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBjb250aW51ZTs8YnI+DQor K8KgIMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQorKyNlbHNlPGJyPg0KKyvCoCDCoCDCoCDCoCDC oCDCoCDCoCBpbnQgZ290X2ZyYW1lOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW50IGxl biA9IGF2Y29kZWNfZGVjb2RlX2F1ZGlvNChjYywgZnJhbWUsICZhbXA7Z290X2ZyYW1lLCAmYW1w O2lucHV0LSZndDtwa3QpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChsZW4gJmx0 OyAwKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogdGhpcyBp cyBvZnRlbiByZWFjaGVkIHdoZW4gc2Vla2luZywgbm90IHN1cmUgd2h5ICovPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaW5wdXQtJmd0O2N1cnJfcGt0X3NpemUgPSAw Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGNvbnRpbnVlOzxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIGlu cHV0LSZndDtjdXJyX3BrdF9zaXplIC09IGxlbjs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKg IGlucHV0LSZndDtjdXJyX3BrdF9idWYgKz0gbGVuOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAg wqAgaWYgKGdvdF9mcmFtZSkgezxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgaW50IHJlcyA9IHN3cl9jb252ZXJ0KHN3ciw8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZhbXA7b3V0cHV0LSZndDtidWZm ZXIsPGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBmcmFtZS0mZ3Q7bmJfc2FtcGxlcyw8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIChjb25zdCB1aW50OF90ICoq KWZyYW1lLSZndDtleHRlbmRlZF9kYXRhLDxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZnJhbWUtJmd0O25iX3NhbXBsZXMpOzxi cj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHJlcyAmbHQ7IDApPGJy Pg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXMgPSAw Ozxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgb3V0cHV0LSZndDtidWZm ZXJfcG9zID0gb3V0cHV0LSZndDtidWZmZXI7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCBp ZiAoIWdvdF9mcmFtZSk8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNv bnRpbnVlOzxicj4NCisrI2VuZGlmPGJyPg0KKys8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKg IGludDY0X3QgZnJhbWVfdHMgPSAtMTs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChm cmFtZS0mZ3Q7cHRzKTxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZnJh bWVfdHMgPSBmcmFtZS0mZ3Q7cHRzOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgZWxzZSBp ZiAoZnJhbWUtJmd0O3BrdF9wdHMpPGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBmcmFtZV90cyA9IGZyYW1lLSZndDtwa3RfcHRzOzxicj4NCisrwqAgwqAgwqAgwqAgwqAg wqAgwqAgZWxzZSBpZiAoZnJhbWUtJmd0O3BrdF9kdHMpPGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBmcmFtZV90cyA9IGZyYW1lLSZndDtwa3RfZHRzOzxicj4NCisrPGJy Pg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCBjb25zdCB1aW50OF90ICoqaW4gPSAoY29uc3QgdWlu dDhfdCAqKilmcmFtZS0mZ3Q7ZXh0ZW5kZWRfZGF0YTs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKg IMKgIGludCBpbl9jb3VudCA9IGZyYW1lLSZndDtuYl9zYW1wbGVzOzxicj4NCisrwqAgwqAgwqAg wqAgwqAgwqAgwqAgaWYgKGlucHV0LSZndDtzZWVrX3RzICZndDsgMCAmYW1wOyZhbXA7IChmcmFt ZV90cyAmZ3Q7PSAwIHx8IGlucHV0LSZndDtwcmV2X2ZyYW1lX2VuZCAmZ3Q7PSAwKSkgezxicj4N CisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3RydWN0IGZmbXBlZ19wcml2YXRl ICpwcml2ID0gaXBfZGF0YS0mZ3Q7cHJpdmF0ZTs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIEFWU3RyZWFtICpzdCA9IHByaXYtJmd0O2lucHV0X2NvbnRleHQtJmd0O3N0 cmVhbXNbcHJpdi0mZ3Q7aW5wdXQtJmd0O3N0cmVhbV9pbmRleF07PGJyPg0KKyvCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoZnJhbWVfdHMgJmd0Oz0gMCk8YnI+DQorK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGZyYW1lX3RzID0gYXZfcmVz Y2FsZV9xKGZyYW1lX3RzLCBzdC0mZ3Q7dGltZV9iYXNlLCBBVl9USU1FX0JBU0VfUSk7PGJyPg0K KyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBlbHNlPGJyPg0KKyvCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBmcmFtZV90cyA9IGlucHV0LSZndDtw cmV2X2ZyYW1lX2VuZDs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlu dDY0X3QgZnJhbWVfZHVyID0gYXZfcmVzY2FsZShmcmFtZS0mZ3Q7bmJfc2FtcGxlcywgQVZfVElN RV9CQVNFLCBzZl9nZXRfcmF0ZShpcF9kYXRhLSZndDtzZikpOzxicj4NCisrwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgaW50NjRfdCBmcmFtZV9lbmQgPSBmcmFtZV90cyArIGZyYW1l X2R1cjs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlucHV0LSZndDtw cmV2X2ZyYW1lX2VuZCA9IGZyYW1lX2VuZDs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIGRfcHJpbnQoJnF1b3Q7c2Vla190czogJWxkLCBmcmFtZV90czogJWxkLCBmcmFt ZV9lbmQ6ICVsZFxuJnF1b3Q7LCBpbnB1dC0mZ3Q7c2Vla190cywgZnJhbWVfdHMsIGZyYW1lX2Vu ZCk7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoZnJhbWVfZW5k ICZsdDs9IGlucHV0LSZndDtzZWVrX3RzKTxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgY29udGludWU7PGJyPg0KKys8YnI+DQorK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIC8qIHNraXAgcGFydCBvZiB0aGlzIGZyYW1lICovPGJyPg0K KyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpbnQ2NF90IHNraXBfc2FtcGxlcyA9 IGF2X3Jlc2NhbGUoaW5wdXQtJmd0O3NlZWtfdHMgLSBmcmFtZV90cywgc2ZfZ2V0X3JhdGUoaXBf ZGF0YS0mZ3Q7c2YpLCBBVl9USU1FX0JBU0UpOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgaW5fY291bnQgLT0gc2tpcF9zYW1wbGVzOzxicj4NCisrwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKGF2X3NhbXBsZV9mbXRfaXNfcGxhbmFyKGZyYW1lLSZn dDtmb3JtYXQpKSB7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCBmb3IgKGludCBpID0gMDsgaSAmbHQ7IGNjLSZndDtjaGFubmVsczsgaSsrKSB7PGJy Pg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBpbltpXSArPSBza2lwX3NhbXBsZXMgKiBzZl9nZXRfc2FtcGxlX3NpemUoaXBfZGF0YS0m Z3Q7c2YpOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgfTxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfSBlbHNlIHs8YnI+ DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICppbiArPSBz a2lwX3NhbXBsZXMgKiBjYy0mZ3Q7Y2hhbm5lbHMgKiBzZl9nZXRfc2FtcGxlX3NpemUoaXBfZGF0 YS0mZ3Q7c2YpOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4N CisrPGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpbnB1dC0mZ3Q7c2Vl a190cyA9IC0xOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW5wdXQt Jmd0O3ByZXZfZnJhbWVfZW5kID0gLTE7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJy Pg0KKys8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIGludCByZXMgPSBzd3JfY29udmVydChz d3IsPGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAm YW1wO291dHB1dC0mZ3Q7YnVmZmVyLDxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgZnJhbWUtJmd0O25iX3NhbXBsZXMsPGJyPg0KKyvCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpbiw8YnI+DQorK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGluX2NvdW50KTs8YnI+DQorK8KgIMKg IMKgIMKgIMKgIMKgIMKgIGlmIChyZXMgJmx0OyAwKTxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgcmVzID0gMDs8YnI+DQorKzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAg wqAgb3V0cHV0LSZndDtidWZmZXJfcG9zID0gb3V0cHV0LSZndDtidWZmZXI7PGJyPg0KKyAjaWYg TElCQVZDT0RFQ19WRVJTSU9OX01BSk9SICZndDs9IDYwPGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBvdXRwdXQtJmd0O2J1ZmZlcl91c2VkX2xlbiA9IHJlcyAqIGNjLSZn dDtjaF9sYXlvdXQubmJfY2hhbm5lbHMgKiBzZl9nZXRfc2FtcGxlX3NpemUoaXBfZGF0YS0mZ3Q7 c2YpOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgb3V0cHV0LSZndDtidWZmZXJfdXNlZF9s ZW4gPSByZXMgKiBjYy0mZ3Q7Y2hfbGF5b3V0Lm5iX2NoYW5uZWxzICogc2ZfZ2V0X3NhbXBsZV9z aXplKGlwX2RhdGEtJmd0O3NmKTs8YnI+DQorICNlbHNlPGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBvdXRwdXQtJmd0O2J1ZmZlcl91c2VkX2xlbiA9IHJlcyAqIGNjLSZn dDtjaGFubmVscyAqIHNmX2dldF9zYW1wbGVfc2l6ZShpcF9kYXRhLSZndDtzZik7PGJyPg0KKyvC oCDCoCDCoCDCoCDCoCDCoCDCoCBvdXRwdXQtJmd0O2J1ZmZlcl91c2VkX2xlbiA9IHJlcyAqIGNj LSZndDtjaGFubmVscyAqIHNmX2dldF9zYW1wbGVfc2l6ZShpcF9kYXRhLSZndDtzZik7PGJyPg0K KyAjZW5kaWY8YnI+DQorKzxicj4NCisgI2lmIExJQkFWQ09ERUNfVkVSU0lPTl9NQUpPUiAmZ3Q7 PSA1Njxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYXZfZnJhbWVfZnJl ZSgmYW1wO2ZyYW1lKTs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIGF2X2ZyYW1lX2ZyZWUo JmFtcDtmcmFtZSk7PGJyPg0KKyAjZWxzZTxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgYXZjb2RlY19mcmVlX2ZyYW1lKCZhbXA7ZnJhbWUpOzxicj4NCisrwqAgwqAgwqAg wqAgwqAgwqAgwqAgYXZjb2RlY19mcmVlX2ZyYW1lKCZhbXA7ZnJhbWUpOzxicj4NCisgI2VuZGlm PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4gb3V0cHV0LSZn dDtidWZmZXJfdXNlZF9sZW47PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KKyvC oCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4gb3V0cHV0LSZndDtidWZmZXJfdXNlZF9sZW47PGJy Pg0KK8KgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDCoC8qIFRoaXMgc2hvdWxkIG5ldmVyIGdl dCBoZXJlLiAqLzxicj4NCivCoCDCoCDCoCDCoHJldHVybiAtSVBfRVJST1JfSU5URVJOQUw7PGJy Pg0KK0BAIC00MzcsMTMgKzQ2OCwxNiBAQCBzdGF0aWMgaW50IGZmbXBlZ19zZWVrKHN0cnVjdCBp bnB1dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSwgZG91YmxlIG9mZnNldCk8YnI+DQorwqAgwqAgwqAg wqBBVlN0cmVhbSAqc3QgPSBwcml2LSZndDtpbnB1dF9jb250ZXh0LSZndDtzdHJlYW1zW3ByaXYt Jmd0O2lucHV0LSZndDtzdHJlYW1faW5kZXhdOzxicj4NCivCoCDCoCDCoCDCoGludCByZXQ7PGJy Pg0KKyA8YnI+DQorLcKgIMKgIMKgIGludDY0X3QgcHRzID0gYXZfcmVzY2FsZV9xKG9mZnNldCAq IEFWX1RJTUVfQkFTRSwgQVZfVElNRV9CQVNFX1EsIHN0LSZndDt0aW1lX2Jhc2UpOzxicj4NCisr wqAgwqAgwqAgcHJpdi0mZ3Q7aW5wdXQtJmd0O3NlZWtfdHMgPSBvZmZzZXQgKiBBVl9USU1FX0JB U0U7PGJyPg0KKyvCoCDCoCDCoCBwcml2LSZndDtpbnB1dC0mZ3Q7cHJldl9mcmFtZV9lbmQgPSAt MTs8YnI+DQorK8KgIMKgIMKgIGludDY0X3QgdHMgPSBhdl9yZXNjYWxlKG9mZnNldCwgc3QtJmd0 O3RpbWVfYmFzZS5kZW4sIHN0LSZndDt0aW1lX2Jhc2UubnVtKTs8YnI+DQorIDxicj4NCivCoCDC oCDCoCDCoGF2Y29kZWNfZmx1c2hfYnVmZmVycyhwcml2LSZndDtjb2RlY19jb250ZXh0KTs8YnI+ DQorwqAgwqAgwqAgwqAvKiBGb3JjZSByZWFkaW5nIGEgbmV3IHBhY2tldCBpbiBuZXh0IGZmbXBl Z19maWxsX2J1ZmZlcigpLiAqLzxicj4NCivCoCDCoCDCoCDCoHByaXYtJmd0O2lucHV0LSZndDtj dXJyX3BrdF9zaXplID0gMDs8YnI+DQorIDxicj4NCistwqAgwqAgwqAgcmV0ID0gYXZfc2Vla19m cmFtZShwcml2LSZndDtpbnB1dF9jb250ZXh0LCBwcml2LSZndDtpbnB1dC0mZ3Q7c3RyZWFtX2lu ZGV4LCBwdHMsIDApOzxicj4NCisrwqAgwqAgwqAgcmV0ID0gYXZmb3JtYXRfc2Vla19maWxlKHBy aXYtJmd0O2lucHV0X2NvbnRleHQsPGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBwcml2LSZndDtpbnB1dC0mZ3Q7c3RyZWFtX2luZGV4LCAwLCB0cywgdHMsIDApOzxicj4N CisgPGJyPg0KK8KgIMKgIMKgIMKgaWYgKHJldCAmbHQ7IDApIHs8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqByZXR1cm4gLUlQX0VSUk9SX0ZVTkNUSU9OX05PVF9TVVBQT1JURUQ7PGJyPg0K Kzxicj4NCitGcm9tIGVjODRmYTdiNGI0YTcyYzE5ZTJhYjA0ZWFjODY0Yzk5ZGY2ZDJlNGUgTW9u IFNlcCAxNyAwMDowMDowMCAyMDAxPGJyPg0KK0Zyb206IGloeTEyMyAmbHQ7PGEgaHJlZj0ibWFp bHRvOmFsYWRpbmFuZHJleXlAZ21haWwuY29tIiB0YXJnZXQ9Il9ibGFuayI+YWxhZGluYW5kcmV5 eUBnbWFpbC5jb208L2E+Jmd0Ozxicj4NCitEYXRlOiBGcmksIDE1IEF1ZyAyMDI1IDIxOjQyOjE5 ICswMzAwPGJyPg0KK1N1YmplY3Q6IFtQQVRDSCAwMi8xMl0gaXAvZmZtcGVnOiBza2lwIHNhbXBs ZXMgb25seSB3aGVuIG5lZWRlZDxicj4NCis8YnI+DQorLS0tPGJyPg0KKyBpcC9mZm1wZWcuYyB8 IDMyICsrKysrKysrKysrKysrKysrKy0tLS0tLS0tLS0tLS0tPGJyPg0KKyAxIGZpbGUgY2hhbmdl ZCwgMTggaW5zZXJ0aW9ucygrKSwgMTQgZGVsZXRpb25zKC0pPGJyPg0KKzxicj4NCitkaWZmIC0t Z2l0wqAgaXAvZmZtcGVnLmPCoCBpcC9mZm1wZWcuYzxicj4NCitpbmRleCBlY2JmMDA1ODIuLjVm NWE0ZjM3YiAxMDA2NDQ8YnI+DQorLS0twqAgaXAvZmZtcGVnLmM8YnI+DQorKysrwqAgaXAvZmZt cGVnLmM8YnI+DQorQEAgLTM5MywyMiArMzkzLDI2IEBAIHN0YXRpYyBpbnQgZmZtcGVnX2ZpbGxf YnVmZmVyKHN0cnVjdCBpbnB1dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSwgQVZGb3JtYXRDb250ZXh0 PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZnJh bWVfdHMgPSBhdl9yZXNjYWxlX3EoZnJhbWVfdHMsIHN0LSZndDt0aW1lX2Jhc2UsIEFWX1RJTUVf QkFTRV9RKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBlbHNlPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZnJhbWVf dHMgPSBpbnB1dC0mZ3Q7cHJldl9mcmFtZV9lbmQ7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCBpbnQ2NF90IGZyYW1lX2R1ciA9IGF2X3Jlc2NhbGUoZnJhbWUtJmd0O25i X3NhbXBsZXMsIEFWX1RJTUVfQkFTRSwgc2ZfZ2V0X3JhdGUoaXBfZGF0YS0mZ3Q7c2YpKTs8YnI+ DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGludDY0X3QgZnJhbWVfZW5kID0g ZnJhbWVfdHMgKyBmcmFtZV9kdXI7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBpbnB1dC0mZ3Q7cHJldl9mcmFtZV9lbmQgPSBmcmFtZV9lbmQ7PGJyPg0KKy3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBkX3ByaW50KCZxdW90O3NlZWtfdHM6ICVsZCwgZnJh bWVfdHM6ICVsZCwgZnJhbWVfZW5kOiAlbGRcbiZxdW90OywgaW5wdXQtJmd0O3NlZWtfdHMsIGZy YW1lX3RzLCBmcmFtZV9lbmQpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgaWYgKGZyYW1lX2VuZCAmbHQ7PSBpbnB1dC0mZ3Q7c2Vla190cyk8YnI+DQorLcKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNvbnRpbnVlOzxicj4NCisgPGJy Pg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAvKiBza2lwIHBhcnQgb2YgdGhp cyBmcmFtZSAqLzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW50NjRf dCBza2lwX3NhbXBsZXMgPSBhdl9yZXNjYWxlKGlucHV0LSZndDtzZWVrX3RzIC0gZnJhbWVfdHMs IHNmX2dldF9yYXRlKGlwX2RhdGEtJmd0O3NmKSwgQVZfVElNRV9CQVNFKTs8YnI+DQorLcKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGluX2NvdW50IC09IHNraXBfc2FtcGxlczs8YnI+ DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChhdl9zYW1wbGVfZm10X2lz X3BsYW5hcihmcmFtZS0mZ3Q7Zm9ybWF0KSkgezxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZm9yIChpbnQgaSA9IDA7IGkgJmx0OyBjYy0mZ3Q7Y2hh bm5lbHM7IGkrKykgezxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgaW5baV0gKz0gc2tpcF9zYW1wbGVzICogc2ZfZ2V0X3NhbXBs ZV9zaXplKGlwX2RhdGEtJmd0O3NmKTs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIGlmIChmcmFtZV90cyAmbHQ7IGlucHV0LSZndDtzZWVrX3RzKSB7PGJyPg0KKyvCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpbnQ2NF90IGZyYW1lX2R1 ciA9IGF2X3Jlc2NhbGUoZnJhbWUtJmd0O25iX3NhbXBsZXMsIEFWX1RJTUVfQkFTRSwgc2ZfZ2V0 X3JhdGUoaXBfZGF0YS0mZ3Q7c2YpKTs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIGludDY0X3QgZnJhbWVfZW5kID0gZnJhbWVfdHMgKyBmcmFtZV9k dXI7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBp bnB1dC0mZ3Q7cHJldl9mcmFtZV9lbmQgPSBmcmFtZV9lbmQ7PGJyPg0KKyvCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBkX3ByaW50KCZxdW90O3NlZWtfdHM6ICVs ZCwgZnJhbWVfdHM6ICVsZCwgZnJhbWVfZW5kOiAlbGRcbiZxdW90OywgaW5wdXQtJmd0O3NlZWtf dHMsIGZyYW1lX3RzLCBmcmFtZV9lbmQpOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKGZyYW1lX2VuZCAmbHQ7PSBpbnB1dC0mZ3Q7c2Vla190 cyk8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIGNvbnRpbnVlOzxicj4NCisrPGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAvKiBza2lwIHBhcnQgb2YgdGhpcyBmcmFtZSAqLzxicj4N CisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW50NjRfdCBz a2lwX3NhbXBsZXMgPSBhdl9yZXNjYWxlKGlucHV0LSZndDtzZWVrX3RzIC0gZnJhbWVfdHMsIHNm X2dldF9yYXRlKGlwX2RhdGEtJmd0O3NmKSwgQVZfVElNRV9CQVNFKTs8YnI+DQorK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGluX2NvdW50IC09IHNraXBfc2Ft cGxlczs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IGlmIChhdl9zYW1wbGVfZm10X2lzX3BsYW5hcihmcmFtZS0mZ3Q7Zm9ybWF0KSkgezxicj4NCisr wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg Zm9yIChpbnQgaSA9IDA7IGkgJmx0OyBjYy0mZ3Q7Y2hhbm5lbHM7IGkrKykgezxicj4NCisrwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgaW5baV0gKz0gc2tpcF9zYW1wbGVzICogc2ZfZ2V0X3NhbXBsZV9zaXplKGlwX2Rh dGEtJmd0O3NmKTs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIH0gZWxzZSB7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqaW4gKz0gc2tpcF9zYW1wbGVzICogY2Mt Jmd0O2NoYW5uZWxzICogc2ZfZ2V0X3NhbXBsZV9zaXplKGlwX2RhdGEtJmd0O3NmKTs8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KKy3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9IGVsc2Ugezxicj4NCistwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKmluICs9IHNraXBfc2FtcGxlcyAq IGNjLSZndDtjaGFubmVscyAqIHNmX2dldF9zYW1wbGVfc2l6ZShpcF9kYXRhLSZndDtzZik7PGJy Pg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBkX3ByaW50 KCZxdW90O3NraXBwaW5nICVsZCBzYW1wbGVzXG4mcXVvdDssIHNraXBfc2FtcGxlcyk7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCisgPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaW5wdXQtJmd0O3NlZWtfdHMgPSAtMTs8YnI+ DQorPGJyPg0KK0Zyb20gNzBhODc2MWZjMWQzMGJmYTMwMjMzMmQwODA3Yjg5YzM3NzZkM2YzMSBN b24gU2VwIDE3IDAwOjAwOjAwIDIwMDE8YnI+DQorRnJvbTogaWh5MTIzICZsdDs8YSBocmVmPSJt YWlsdG86YWxhZGluYW5kcmV5eUBnbWFpbC5jb20iIHRhcmdldD0iX2JsYW5rIj5hbGFkaW5hbmRy ZXl5QGdtYWlsLmNvbTwvYT4mZ3Q7PGJyPg0KK0RhdGU6IFNhdCwgMTYgQXVnIDIwMjUgMDI6NDM6 NTUgKzAzMDA8YnI+DQorU3ViamVjdDogW1BBVENIIDAzLzEyXSBpcC9mZm1wZWc6IHJlbW92ZSBl eGNlc3NpdmUgdmVyc2lvbiBjaGVja3M8YnI+DQorPGJyPg0KK2ZmbXBlZyBkb3dubG9hZCBwYWdl IHN0YXRlcyB0aGF0IHY0LjAuNiBoYXM8YnI+DQorLSBsaWJhdnV0aWwgNTYuMTQuMTAwPGJyPg0K Ky0gbGliYXZjb2RlYyA1OC4xOC4xMDA8YnI+DQorLSBsaWJhdmZvcm1hdCA1OC4xMi4xMDA8YnI+ DQorKDxhIGhyZWY9Imh0dHBzOi8vZmZtcGVnLm9yZy9vbGRkb3dubG9hZC5odG1sIiByZWw9Im5v cmVmZXJyZXIiIHRhcmdldD0iX2JsYW5rIj5odHRwczovL2ZmbXBlZy5vcmcvb2xkZG93bmxvYWQu aHRtbDwvYT4pPGJyPg0KKzxicj4NCitBZnRlciByZW1vdmluZyBhbGwgY2hlY2tzIGZvciB2ZXJz aW9ucyBsb3dlciB0aGFuIHRoZXNlLCB0aGUgcGx1Z2luPGJyPg0KK3N0aWxsIGNvbXBpbGVzIHdp dGggdjMuMy45IGhlYWRlcnMuPGJyPg0KKzxicj4NCitBZnRlciBhbGwsIHdoeSBiZSBiZXR0ZXIg d2l0aCBjb21wYXRpYmlsaXR5IHRoYW4gZGV2ZWxvcGVycyB0aGVtc2VsdmVzPzxicj4NCistLS08 YnI+DQorIGlwL2ZmbXBlZy5jIHwgMTA5ICsrKysrKysrKysrLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS08YnI+DQorIDEgZmlsZSBjaGFuZ2VkLCAyMyBpbnNlcnRpb25z KCspLCA4NiBkZWxldGlvbnMoLSk8YnI+DQorPGJyPg0KK2RpZmYgLS1naXTCoCBpcC9mZm1wZWcu Y8KgIGlwL2ZmbXBlZy5jPGJyPg0KK2luZGV4IDVmNWE0ZjM3Yi4uZjZhMTFmNDUwIDEwMDY0NDxi cj4NCistLS3CoCBpcC9mZm1wZWcuYzxicj4NCisrKyvCoCBpcC9mZm1wZWcuYzxicj4NCitAQCAt MjUsNyArMjUsNiBAQDxicj4NCisgI2luY2x1ZGUgJnF1b3Q7Li4vY29uZmlnL2ZmbXBlZy5oJnF1 b3Q7PGJyPg0KKyAjZW5kaWY8YnI+DQorIDxicj4NCistI2luY2x1ZGUgJmx0O3N0ZGlvLmgmZ3Q7 PGJyPg0KKyAjaW5jbHVkZSAmbHQ7bGliYXZjb2RlYy9hdmNvZGVjLmgmZ3Q7PGJyPg0KKyAjaW5j bHVkZSAmbHQ7bGliYXZmb3JtYXQvYXZmb3JtYXQuaCZndDs8YnI+DQorICNpbmNsdWRlICZsdDts aWJhdmZvcm1hdC9hdmlvLmgmZ3Q7PGJyPg0KK0BAIC00Myw3ICs0Miw2IEBAPGJyPg0KKyBzdHJ1 Y3QgZmZtcGVnX2lucHV0IHs8YnI+DQorwqAgwqAgwqAgwqBBVlBhY2tldCBwa3Q7PGJyPg0KK8Kg IMKgIMKgIMKgaW50IGN1cnJfcGt0X3NpemU7PGJyPg0KKy3CoCDCoCDCoCB1aW50OF90ICpjdXJy X3BrdF9idWY7PGJyPg0KK8KgIMKgIMKgIMKgaW50NjRfdCBzZWVrX3RzOzxicj4NCivCoCDCoCDC oCDCoGludDY0X3QgcHJldl9mcmFtZV9lbmQ7PGJyPg0KK8KgIMKgIMKgIMKgaW50IHN0cmVhbV9p bmRleDs8YnI+DQorQEAgLTgwLDE3ICs3OCwxMiBAQCBzdGF0aWMgc3RydWN0IGZmbXBlZ19pbnB1 dCAqZmZtcGVnX2lucHV0X2NyZWF0ZSh2b2lkKTxicj4NCivCoCDCoCDCoCDCoGlucHV0LSZndDtj dXJyX3BrdF9zaXplID0gMDs8YnI+DQorwqAgwqAgwqAgwqBpbnB1dC0mZ3Q7c2Vla190cyA9IC0x Ozxicj4NCivCoCDCoCDCoCDCoGlucHV0LSZndDtwcmV2X2ZyYW1lX2VuZCA9IC0xOzxicj4NCist wqAgwqAgwqAgaW5wdXQtJmd0O2N1cnJfcGt0X2J1ZiA9IGlucHV0LSZndDtwa3QuZGF0YTs8YnI+ DQorwqAgwqAgwqAgwqByZXR1cm4gaW5wdXQ7PGJyPg0KKyB9PGJyPg0KKyA8YnI+DQorIHN0YXRp YyB2b2lkIGZmbXBlZ19pbnB1dF9mcmVlKHN0cnVjdCBmZm1wZWdfaW5wdXQgKmlucHV0KTxicj4N Cisgezxicj4NCistI2lmIExJQkFWQ09ERUNfVkVSU0lPTl9NQUpPUiAmZ3Q7PSA1Njxicj4NCivC oCDCoCDCoCDCoGF2X3BhY2tldF91bnJlZigmYW1wO2lucHV0LSZndDtwa3QpOzxicj4NCistI2Vs c2U8YnI+DQorLcKgIMKgIMKgIGF2X2ZyZWVfcGFja2V0KCZhbXA7aW5wdXQtJmd0O3BrdCk7PGJy Pg0KKy0jZW5kaWY8YnI+DQorwqAgwqAgwqAgwqBmcmVlKGlucHV0KTs8YnI+DQorIH08YnI+DQor IDxicj4NCitAQCAtMTMyLDcgKzEyNSw3IEBAIHN0YXRpYyB2b2lkIGZmbXBlZ19pbml0KHZvaWQp PGJyPg0KKyA8YnI+DQorwqAgwqAgwqAgwqBhdl9sb2dfc2V0X2xldmVsKEFWX0xPR19RVUlFVCk7 PGJyPg0KKyA8YnI+DQorLSNpZiBMSUJBVkNPREVDX1ZFUlNJT05fSU5UICZsdDsgQVZfVkVSU0lP Tl9JTlQoNTgsIDE4LCAxMDApPGJyPg0KKysjaWYgTElCQVZGT1JNQVRfVkVSU0lPTl9JTlQgJmx0 OyBBVl9WRVJTSU9OX0lOVCg1OCwgOSwgMTAwKTxicj4NCivCoCDCoCDCoCDCoC8qIFdlIGNvdWxk IHJlZ2lzdGVyIGRlY29kZXJzIGV4cGxpY2l0bHkgdG8gc2F2ZSBtZW1vcnksIGJ1dCB3ZSBoYXZl IHRvPGJyPg0KK8KgIMKgIMKgIMKgICogYmUgY2FyZWZ1bCBhYm91dCBjb21wYXRpYmlsaXR5LiAq Lzxicj4NCivCoCDCoCDCoCDCoGF2X3JlZ2lzdGVyX2FsbCgpOzxicj4NCitAQCAtMTQ5LDkgKzE0 Miw3IEBAIHN0YXRpYyBpbnQgZmZtcGVnX29wZW4oc3RydWN0IGlucHV0X3BsdWdpbl9kYXRhICpp cF9kYXRhKTxicj4NCivCoCDCoCDCoCDCoEFWQ29kZWMgY29uc3QgKmNvZGVjOzxicj4NCivCoCDC oCDCoCDCoEFWQ29kZWNDb250ZXh0ICpjYyA9IE5VTEw7PGJyPg0KK8KgIMKgIMKgIMKgQVZGb3Jt YXRDb250ZXh0ICppYyA9IE5VTEw7PGJyPg0KKy0jaWYgTElCQVZDT0RFQ19WRVJTSU9OX0lOVCAm Z3Q7PSBBVl9WRVJTSU9OX0lOVCg1NywgNDgsIDEwMSk8YnI+DQorwqAgwqAgwqAgwqBBVkNvZGVj UGFyYW1ldGVycyAqY3AgPSBOVUxMOzxicj4NCistI2VuZGlmPGJyPg0KK8KgIMKgIMKgIMKgU3dy Q29udGV4dCAqc3dyID0gTlVMTDs8YnI+DQorIDxicj4NCivCoCDCoCDCoCDCoGZmbXBlZ19pbml0 KCk7PGJyPg0KK0BAIC0xNzEsMjAgKzE2MiwxMSBAQCBzdGF0aWMgaW50IGZmbXBlZ19vcGVuKHN0 cnVjdCBpbnB1dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqB9PGJyPg0KKyA8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBp ICZsdDsgaWMtJmd0O25iX3N0cmVhbXM7IGkrKykgezxicj4NCistPGJyPg0KKy0jaWYgTElCQVZD T0RFQ19WRVJTSU9OX0lOVCAmZ3Q7PSBBVl9WRVJTSU9OX0lOVCg1NywgNDgsIDEwMSk8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBjcCA9IGljLSZndDtzdHJlYW1zW2ld LSZndDtjb2RlY3Bhcjs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBp ZiAoY3AtJmd0O2NvZGVjX3R5cGUgPT0gQVZNRURJQV9UWVBFX0FVRElPKSB7PGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc3RyZWFtX2luZGV4ID0g aTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBi cmVhazs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KKy0j ZWxzZTxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY2MgPSBpYy0mZ3Q7 c3RyZWFtc1tpXS0mZ3Q7Y29kZWM7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBpZiAoY2MtJmd0O2NvZGVjX3R5cGUgPT0gQVZNRURJQV9UWVBFX0FVRElPKSB7PGJyPg0K Ky3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdHJlYW1faW5k ZXggPSBpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgYnJlYWs7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0K Ky0jZW5kaWY8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KKyA8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoc3RyZWFtX2luZGV4ID09IC0xKSB7PGJyPg0KK0BAIC0x OTMsMTMgKzE3NSw5IEBAIHN0YXRpYyBpbnQgZmZtcGVnX29wZW4oc3RydWN0IGlucHV0X3BsdWdp bl9kYXRhICppcF9kYXRhKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oGJyZWFrOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorIDxicj4NCistI2lm IExJQkFWQ09ERUNfVkVSU0lPTl9JTlQgJmd0Oz0gQVZfVkVSU0lPTl9JTlQoNTcsIDQ4LCAxMDEp PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY29kZWMgPSBhdmNvZGVjX2ZpbmRfZGVjb2Rl cihjcC0mZ3Q7Y29kZWNfaWQpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGNjID0gYXZj b2RlY19hbGxvY19jb250ZXh0Myhjb2RlYyk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg YXZjb2RlY19wYXJhbWV0ZXJzX3RvX2NvbnRleHQoY2MsIGNwKTs8YnI+DQorLSNlbHNlPGJyPg0K Ky3CoCDCoCDCoCDCoCDCoCDCoCDCoCBjb2RlYyA9IGF2Y29kZWNfZmluZF9kZWNvZGVyKGNjLSZn dDtjb2RlY19pZCk7PGJyPg0KKy0jZW5kaWY8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBp ZiAoIWNvZGVjKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZF9w cmludCgmcXVvdDtjb2RlYyBub3QgZm91bmQ6ICVkLCAlc1xuJnF1b3Q7LCBjYy0mZ3Q7Y29kZWNf aWQsIGF2Y29kZWNfZ2V0X25hbWUoY2MtJmd0O2NvZGVjX2lkKSk7PGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZXJyID0gLUlQX0VSUk9SX1VOU1VQUE9SVEVEX0ZJTEVf VFlQRTs8YnI+DQorQEAgLTIxNyw5ICsxOTUsNyBAQCBzdGF0aWMgaW50IGZmbXBlZ19vcGVuKHN0 cnVjdCBpbnB1dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSk8YnI+DQorIDxicj4NCivCoCDCoCDCoCDC oGlmIChlcnIgJmx0OyAwKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogQ2xlYW4g dXAuwqAgY2MgaXMgbmV2ZXIgb3BlbmVkIGF0IHRoaXMgcG9pbnQuwqAgKFNlZSBhYm92ZSBhc3N1 bXB0aW9uLikgKi88YnI+DQorLSNpZiBMSUJBVkNPREVDX1ZFUlNJT05fSU5UICZndDs9IEFWX1ZF UlNJT05fSU5UKDU3LCA0OCwgMTAxKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGF2Y29k ZWNfZnJlZV9jb250ZXh0KCZhbXA7Y2MpOzxicj4NCistI2VuZGlmPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgYXZmb3JtYXRfY2xvc2VfaW5wdXQoJmFtcDtpYyk7PGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgcmV0dXJuIGVycjs8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KK0BAIC0y MzEsOSArMjA3LDcgQEAgc3RhdGljIGludCBmZm1wZWdfb3BlbihzdHJ1Y3QgaW5wdXRfcGx1Z2lu X2RhdGEgKmlwX2RhdGEpPGJyPg0KK8KgIMKgIMKgIMKgcHJpdi0mZ3Q7aW5wdXQgPSBmZm1wZWdf aW5wdXRfY3JlYXRlKCk7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHByaXYtJmd0O2lucHV0ID09IE5V TEwpIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBhdmNvZGVjX2Nsb3NlKGNjKTs8YnI+ DQorLSNpZiBMSUJBVkNPREVDX1ZFUlNJT05fSU5UICZndDs9IEFWX1ZFUlNJT05fSU5UKDU3LCA0 OCwgMTAxKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGF2Y29kZWNfZnJlZV9jb250ZXh0 KCZhbXA7Y2MpOzxicj4NCistI2VuZGlmPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYXZm b3JtYXRfY2xvc2VfaW5wdXQoJmFtcDtpYyk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg ZnJlZShwcml2KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLUlQX0VSUk9S X0lOVEVSTkFMOzxicj4NCitAQCAtMjQ0LDcgKzIxOCw3IEBAIHN0YXRpYyBpbnQgZmZtcGVnX29w ZW4oc3RydWN0IGlucHV0X3BsdWdpbl9kYXRhICppcF9kYXRhKTxicj4NCivCoCDCoCDCoCDCoC8q IFByZXBhcmUgZm9yIHJlc2FtcGxpbmcuICovPGJyPg0KK8KgIMKgIMKgIMKgb3V0X3NhbXBsZV9y YXRlID0gbWluX3UoY2MtJmd0O3NhbXBsZV9yYXRlLCAzODQwMDApOzxicj4NCivCoCDCoCDCoCDC oHN3ciA9IHN3cl9hbGxvYygpOzxicj4NCistI2lmIExJQkFWQ09ERUNfVkVSU0lPTl9NQUpPUiAm Z3Q7PSA2MDxicj4NCisrI2lmIExJQkFWQ09ERUNfVkVSU0lPTl9JTlQgJmd0Oz0gQVZfVkVSU0lP Tl9JTlQoNTksIDI0LCAxMDApPGJyPg0KK8KgIMKgIMKgIMKgaWYgKGNjLSZndDtjaF9sYXlvdXQu b3JkZXIgPT0gQVZfQ0hBTk5FTF9PUkRFUl9VTlNQRUMpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgYXZfY2hhbm5lbF9sYXlvdXRfZGVmYXVsdCgmYW1wO2NjLSZndDtjaF9sYXlvdXQsIGNj LSZndDtjaF9sYXlvdXQubmJfY2hhbm5lbHMpOzxicj4NCivCoCDCoCDCoCDCoGF2X29wdF9zZXRf Y2hsYXlvdXQoc3dyLCAmcXVvdDtpbl9jaGxheW91dCZxdW90OyzCoCDCoCZhbXA7Y2MtJmd0O2No X2xheW91dCwgMCk7PGJyPg0KK0BAIC0yNTksNyArMjMzLDcgQEAgc3RhdGljIGludCBmZm1wZWdf b3BlbihzdHJ1Y3QgaW5wdXRfcGx1Z2luX2RhdGEgKmlwX2RhdGEpPGJyPg0KK8KgIMKgIMKgIMKg cHJpdi0mZ3Q7c3dyID0gc3dyOzxicj4NCisgPGJyPg0KK8KgIMKgIMKgIMKgaXBfZGF0YS0mZ3Q7 cHJpdmF0ZSA9IHByaXY7PGJyPg0KKy0jaWYgTElCQVZDT0RFQ19WRVJTSU9OX01BSk9SICZndDs9 IDYwPGJyPg0KKysjaWYgTElCQVZDT0RFQ19WRVJTSU9OX0lOVCAmZ3Q7PSBBVl9WRVJTSU9OX0lO VCg1OSwgMjQsIDEwMCk8YnI+DQorwqAgwqAgwqAgwqBpcF9kYXRhLSZndDtzZiA9IHNmX3JhdGUo b3V0X3NhbXBsZV9yYXRlKSB8IHNmX2NoYW5uZWxzKGNjLSZndDtjaF9sYXlvdXQubmJfY2hhbm5l bHMpOzxicj4NCisgI2Vsc2U8YnI+DQorwqAgwqAgwqAgwqBpcF9kYXRhLSZndDtzZiA9IHNmX3Jh dGUob3V0X3NhbXBsZV9yYXRlKSB8IHNmX2NoYW5uZWxzKGNjLSZndDtjaGFubmVscyk7PGJyPg0K K0BAIC0yODEsMTAgKzI1NSwxMiBAQCBzdGF0aWMgaW50IGZmbXBlZ19vcGVuKHN0cnVjdCBpbnB1 dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSk8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKg IMKgc3dyX2luaXQoc3dyKTs8YnI+DQorwqAgwqAgwqAgwqBpcF9kYXRhLSZndDtzZiB8PSBzZl9o b3N0X2VuZGlhbigpOzxicj4NCistI2lmIExJQkFWQ09ERUNfVkVSU0lPTl9NQUpPUiAmZ3Q7PSA2 MDxicj4NCistwqAgwqAgwqAgY2hhbm5lbF9tYXBfaW5pdF93YXZlZXgoY2MtJmd0O2NoX2xheW91 dC5uYl9jaGFubmVscywgY2MtJmd0O2NoX2xheW91dC51Lm1hc2ssIGlwX2RhdGEtJmd0O2NoYW5u ZWxfbWFwKTs8YnI+DQorKyNpZiBMSUJBVkNPREVDX1ZFUlNJT05fSU5UICZndDs9IEFWX1ZFUlNJ T05fSU5UKDU5LCAyNCwgMTAwKTxicj4NCisrwqAgwqAgwqAgY2hhbm5lbF9tYXBfaW5pdF93YXZl ZXgoY2MtJmd0O2NoX2xheW91dC5uYl9jaGFubmVscyw8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIGNjLSZndDtjaF9sYXlvdXQudS5tYXNrLCBpcF9kYXRhLSZndDtjaGFu bmVsX21hcCk7PGJyPg0KKyAjZWxzZTxicj4NCistwqAgwqAgwqAgY2hhbm5lbF9tYXBfaW5pdF93 YXZlZXgoY2MtJmd0O2NoYW5uZWxzLCBjYy0mZ3Q7Y2hhbm5lbF9sYXlvdXQsIGlwX2RhdGEtJmd0 O2NoYW5uZWxfbWFwKTs8YnI+DQorK8KgIMKgIMKgIGNoYW5uZWxfbWFwX2luaXRfd2F2ZWV4KGNj LSZndDtjaGFubmVscyw8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNj LSZndDtjaGFubmVsX2xheW91dCwgaXBfZGF0YS0mZ3Q7Y2hhbm5lbF9tYXApOzxicj4NCisgI2Vu ZGlmPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KKyB9PGJyPg0KK0BAIC0yOTQsOSAr MjcwLDcgQEAgc3RhdGljIGludCBmZm1wZWdfY2xvc2Uoc3RydWN0IGlucHV0X3BsdWdpbl9kYXRh ICppcF9kYXRhKTxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBmZm1wZWdfcHJpdmF0ZSAqcHJpdiA9 IGlwX2RhdGEtJmd0O3ByaXZhdGU7PGJyPg0KKyA8YnI+DQorwqAgwqAgwqAgwqBhdmNvZGVjX2Ns b3NlKHByaXYtJmd0O2NvZGVjX2NvbnRleHQpOzxicj4NCistI2lmIExJQkFWQ09ERUNfVkVSU0lP Tl9JTlQgJmd0Oz0gQVZfVkVSU0lPTl9JTlQoNTcsIDQ4LCAxMDEpPGJyPg0KK8KgIMKgIMKgIMKg YXZjb2RlY19mcmVlX2NvbnRleHQoJmFtcDtwcml2LSZndDtjb2RlY19jb250ZXh0KTs8YnI+DQor LSNlbmRpZjxicj4NCivCoCDCoCDCoCDCoGF2Zm9ybWF0X2Nsb3NlX2lucHV0KCZhbXA7cHJpdi0m Z3Q7aW5wdXRfY29udGV4dCk7PGJyPg0KK8KgIMKgIMKgIMKgc3dyX2ZyZWUoJmFtcDtwcml2LSZn dDtzd3IpOzxicj4NCivCoCDCoCDCoCDCoGZmbXBlZ19pbnB1dF9mcmVlKHByaXYtJmd0O2lucHV0 KTs8YnI+DQorQEAgLTMxMCwzOSArMjg0LDI3IEBAIHN0YXRpYyBpbnQgZmZtcGVnX2Nsb3NlKHN0 cnVjdCBpbnB1dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSk8YnI+DQorwqAgKiBUaGlzIHJldHVybnMg dGhlIG51bWJlciBvZiBieXRlcyBhZGRlZCB0byB0aGUgYnVmZmVyLjxicj4NCivCoCAqIEl0IHJl dHVybnMgJmx0OyAwIG9uIGVycm9yLsKgIDAgb24gRU9GLjxicj4NCivCoCAqLzxicj4NCistc3Rh dGljIGludCBmZm1wZWdfZmlsbF9idWZmZXIoc3RydWN0IGlucHV0X3BsdWdpbl9kYXRhICppcF9k YXRhLCBBVkZvcm1hdENvbnRleHQgKmljLCBBVkNvZGVjQ29udGV4dCAqY2MsPGJyPg0KKy3CoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdHJ1Y3QgZmZtcGVnX2lucHV0 ICppbnB1dCwgc3RydWN0IGZmbXBlZ19vdXRwdXQgKm91dHB1dCwgU3dyQ29udGV4dCAqc3dyKTxi cj4NCisrc3RhdGljIGludCBmZm1wZWdfZmlsbF9idWZmZXIoc3RydWN0IGlucHV0X3BsdWdpbl9k YXRhICppcF9kYXRhLDxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgQVZGb3JtYXRDb250ZXh0 ICppYywgQVZDb2RlY0NvbnRleHQgKmNjLDxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3Ry dWN0IGZmbXBlZ19pbnB1dCAqaW5wdXQsIHN0cnVjdCBmZm1wZWdfb3V0cHV0ICpvdXRwdXQsPGJy Pg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCBTd3JDb250ZXh0ICpzd3IpPGJyPg0KKyB7PGJyPg0K Ky0jaWYgTElCQVZDT0RFQ19WRVJTSU9OX01BSk9SICZndDs9IDU2PGJyPg0KK8KgIMKgIMKgIMKg QVZGcmFtZSAqZnJhbWUgPSBhdl9mcmFtZV9hbGxvYygpOzxicj4NCistI2Vsc2U8YnI+DQorLcKg IMKgIMKgIEFWRnJhbWUgKmZyYW1lID0gYXZjb2RlY19hbGxvY19mcmFtZSgpOzxicj4NCistI2Vu ZGlmPGJyPg0KK8KgIMKgIMKgIMKgd2hpbGUgKDEpIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBpZiAoaW5wdXQtJmd0O2N1cnJfcGt0X3NpemUgJmx0Oz0gMCkgezxicj4NCistI2lmIExJ QkFWQ09ERUNfVkVSU0lPTl9NQUpPUiAmZ3Q7PSA1Njxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoGF2X3BhY2tldF91bnJlZigmYW1wO2lucHV0LSZndDtwa3QpOzxicj4N CistI2Vsc2U8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGF2X2ZyZWVf cGFja2V0KCZhbXA7aW5wdXQtJmd0O3BrdCk7PGJyPg0KKy0jZW5kaWY8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoYXZfcmVhZF9mcmFtZShpYywgJmFtcDtpbnB1 dC0mZ3Q7cGt0KSAmbHQ7IDApIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAvKiBGb3JjZSBFT0Ygb25jZSB3ZSBjYW4gcmVhZCBubyBsb25nZXIu ICovPGJyPg0KKy0jaWYgTElCQVZDT0RFQ19WRVJTSU9OX01BSk9SICZndDs9IDU2PGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYXZfZnJhbWVfZnJl ZSgmYW1wO2ZyYW1lKTs8YnI+DQorLSNlbHNlPGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBhdmNvZGVjX2ZyZWVfZnJhbWUoJmFtcDtmcmFtZSk7PGJy Pg0KKy0jZW5kaWY8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqByZXR1cm4gMDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqB9PGJyPg0KKyA8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAo aW5wdXQtJmd0O3BrdC5zdHJlYW1faW5kZXggIT0gaW5wdXQtJmd0O3N0cmVhbV9pbmRleCk8YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBjb250aW51 ZTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpbnB1dC0mZ3Q7Y3Vy cl9wa3Rfc2l6ZSA9IGlucHV0LSZndDtwa3Quc2l6ZTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIGlucHV0LSZndDtjdXJyX3BrdF9idWYgPSBpbnB1dC0mZ3Q7cGt0LmRh dGE7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaW5wdXQtJmd0O2N1 cnJfc2l6ZSArPSBpbnB1dC0mZ3Q7cGt0LnNpemU7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgaW5wdXQtJmd0O2N1cnJfZHVyYXRpb24gKz0gaW5wdXQtJmd0O3BrdC5k dXJhdGlvbjs8YnI+DQorIDxicj4NCistI2lmIExJQkFWQ09ERUNfVkVSU0lPTl9JTlQgJmd0Oz0g QVZfVkVSU0lPTl9JTlQoNTcsIDQ4LCAxMDEpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgaW50IHNlbmRfcmVzdWx0ID0gYXZjb2RlY19zZW5kX3BhY2tldChjYywgJmFt cDtpbnB1dC0mZ3Q7cGt0KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBpZiAoc2VuZF9yZXN1bHQgIT0gMCAmYW1wOyZhbXA7IHNlbmRfcmVzdWx0ICE9IEFWRVJST1Io RUFHQUlOKSkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoGRfcHJpbnQoJnF1b3Q7YXZjb2RlY19zZW5kX3BhY2tldCgpIHJldHVybmVkICVkXG4m cXVvdDssIHNlbmRfcmVzdWx0KTs8YnI+DQorQEAgLTM1NSwzMiArMzE3LDE3IEBAIHN0YXRpYyBp bnQgZmZtcGVnX2ZpbGxfYnVmZmVyKHN0cnVjdCBpbnB1dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSwg QVZGb3JtYXRDb250ZXh0PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHJldHVybiAtSVBfRVJST1JfSU5URVJOQUw7PGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCistI2VuZGlmPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgfTxicj4NCisgPGJyPg0KKy0jaWYgTElCQVZDT0RFQ19WRVJTSU9OX0lOVCAmZ3Q7 PSBBVl9WRVJTSU9OX0lOVCg1NywgNDgsIDEwMSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBpbnQgcmVjdl9yZXN1bHQgPSBhdmNvZGVjX3JlY2VpdmVfZnJhbWUoY2MsIGZyYW1lKTs8YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAocmVjdl9yZXN1bHQgJmx0OyAwKSB7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaW5wdXQtJmd0O2N1cnJfcGt0X3Np emUgPSAwOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGNvbnRpbnVl Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorLSNlbHNlPGJyPg0KKy3CoCDC oCDCoCDCoCDCoCDCoCDCoCBpbnQgZ290X2ZyYW1lOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAg wqAgaW50IGxlbiA9IGF2Y29kZWNfZGVjb2RlX2F1ZGlvNChjYywgZnJhbWUsICZhbXA7Z290X2Zy YW1lLCAmYW1wO2lucHV0LSZndDtwa3QpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYg KGxlbiAmbHQ7IDApIHs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIC8q IHRoaXMgaXMgb2Z0ZW4gcmVhY2hlZCB3aGVuIHNlZWtpbmcsIG5vdCBzdXJlIHdoeSAqLzxicj4N CistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW5wdXQtJmd0O2N1cnJfcGt0X3Np emUgPSAwOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY29udGludWU7 PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDC oCBpZiAoIWdvdF9mcmFtZSk8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IGNvbnRpbnVlOzxicj4NCistI2VuZGlmPGJyPg0KKyA8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBpbnQ2NF90IGZyYW1lX3RzID0gLTE7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg aWYgKGZyYW1lLSZndDtwdHMpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgZnJhbWVfdHMgPSBmcmFtZS0mZ3Q7cHRzOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAg ZWxzZSBpZiAoZnJhbWUtJmd0O3BrdF9wdHMpPGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBmcmFtZV90cyA9IGZyYW1lLSZndDtwa3RfcHRzOzxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoGVsc2UgaWYgKGZyYW1lLSZndDtwa3RfZHRzKTxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZyYW1lX3RzID0gZnJhbWUtJmd0O3BrdF9kdHM7PGJy Pg0KKyA8YnI+DQorQEAgLTM5NSw3ICszNDIsNyBAQCBzdGF0aWMgaW50IGZmbXBlZ19maWxsX2J1 ZmZlcihzdHJ1Y3QgaW5wdXRfcGx1Z2luX2RhdGEgKmlwX2RhdGEsIEFWRm9ybWF0Q29udGV4dDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZyYW1l X3RzID0gaW5wdXQtJmd0O3ByZXZfZnJhbWVfZW5kOzxicj4NCisgPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGZyYW1lX3RzICZsdDsgaW5wdXQtJmd0O3NlZWtf dHMpIHs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IGludDY0X3QgZnJhbWVfZHVyID0gYXZfcmVzY2FsZShmcmFtZS0mZ3Q7bmJfc2FtcGxlcywgQVZf VElNRV9CQVNFLCBzZl9nZXRfcmF0ZShpcF9kYXRhLSZndDtzZikpOzxicj4NCisrwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW50NjRfdCBmcmFtZV9kdXIgPSBh dl9yZXNjYWxlKGZyYW1lLSZndDtuYl9zYW1wbGVzLCBBVl9USU1FX0JBU0UsIGZyYW1lLSZndDtz YW1wbGVfcmF0ZSk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgaW50NjRfdCBmcmFtZV9lbmQgPSBmcmFtZV90cyArIGZyYW1lX2R1cjs8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpbnB1dC0mZ3Q7 cHJldl9mcmFtZV9lbmQgPSBmcmFtZV9lbmQ7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZF9wcmludCgmcXVvdDtzZWVrX3RzOiAlbGQsIGZyYW1l X3RzOiAlbGQsIGZyYW1lX2VuZDogJWxkXG4mcXVvdDssIGlucHV0LSZndDtzZWVrX3RzLCBmcmFt ZV90cywgZnJhbWVfZW5kKTs8YnI+DQorQEAgLTQwMywxNCArMzUwLDE0IEBAIHN0YXRpYyBpbnQg ZmZtcGVnX2ZpbGxfYnVmZmVyKHN0cnVjdCBpbnB1dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSwgQVZG b3JtYXRDb250ZXh0PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgY29udGludWU7PGJyPg0KKyA8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiBza2lwIHBhcnQgb2YgdGhpcyBm cmFtZSAqLzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgaW50NjRfdCBza2lwX3NhbXBsZXMgPSBhdl9yZXNjYWxlKGlucHV0LSZndDtzZWVrX3RzIC0g ZnJhbWVfdHMsIHNmX2dldF9yYXRlKGlwX2RhdGEtJmd0O3NmKSwgQVZfVElNRV9CQVNFKTs8YnI+ DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGludDY0X3Qg c2tpcF9zYW1wbGVzID0gYXZfcmVzY2FsZShpbnB1dC0mZ3Q7c2Vla190cyAtIGZyYW1lX3RzLCBm cmFtZS0mZ3Q7c2FtcGxlX3JhdGUsIEFWX1RJTUVfQkFTRSk7PGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaW5fY291bnQgLT0gc2tpcF9zYW1wbGVz Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlm IChhdl9zYW1wbGVfZm10X2lzX3BsYW5hcihmcmFtZS0mZ3Q7Zm9ybWF0KSkgezxicj4NCistwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZm9y IChpbnQgaSA9IDA7IGkgJmx0OyBjYy0mZ3Q7Y2hhbm5lbHM7IGkrKykgezxicj4NCisrwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZm9yIChp bnQgaSA9IDA7IGkgJmx0OyBzZl9nZXRfY2hhbm5lbHMoaXBfZGF0YS0mZ3Q7c2YpOyBpKyspIHs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqBpbltpXSArPSBza2lwX3NhbXBsZXMgKiBzZl9nZXRfc2FtcGxl X3NpemUoaXBfZGF0YS0mZ3Q7c2YpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9IGVsc2Ugezxicj4NCistwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKmluICs9IHNraXBf c2FtcGxlcyAqIGNjLSZndDtjaGFubmVscyAqIHNmX2dldF9zYW1wbGVfc2l6ZShpcF9kYXRhLSZn dDtzZik7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCAqaW4gKz0gc2tpcF9zYW1wbGVzICogc2ZfZ2V0X2ZyYW1lX3NpemUoaXBf ZGF0YS0mZ3Q7c2YpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBkX3ByaW50KCZxdW90O3NraXBwaW5nICVsZCBzYW1wbGVzXG4mcXVvdDssIHNraXBf c2FtcGxlcyk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4N CitAQCAtNDI4LDE3ICszNzUsOSBAQCBzdGF0aWMgaW50IGZmbXBlZ19maWxsX2J1ZmZlcihzdHJ1 Y3QgaW5wdXRfcGx1Z2luX2RhdGEgKmlwX2RhdGEsIEFWRm9ybWF0Q29udGV4dDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJlcyA9IDA7PGJyPg0KKyA8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqBvdXRwdXQtJmd0O2J1ZmZlcl9wb3MgPSBvdXRwdXQtJmd0O2J1 ZmZlcjs8YnI+DQorLSNpZiBMSUJBVkNPREVDX1ZFUlNJT05fTUFKT1IgJmd0Oz0gNjA8YnI+DQor LcKgIMKgIMKgIMKgIMKgIMKgIMKgIG91dHB1dC0mZ3Q7YnVmZmVyX3VzZWRfbGVuID0gcmVzICog Y2MtJmd0O2NoX2xheW91dC5uYl9jaGFubmVscyAqIHNmX2dldF9zYW1wbGVfc2l6ZShpcF9kYXRh LSZndDtzZik7PGJyPg0KKy0jZWxzZTxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgb3V0cHV0 LSZndDtidWZmZXJfdXNlZF9sZW4gPSByZXMgKiBjYy0mZ3Q7Y2hhbm5lbHMgKiBzZl9nZXRfc2Ft cGxlX3NpemUoaXBfZGF0YS0mZ3Q7c2YpOzxicj4NCistI2VuZGlmPGJyPg0KKyvCoCDCoCDCoCDC oCDCoCDCoCDCoCBvdXRwdXQtJmd0O2J1ZmZlcl91c2VkX2xlbiA9IHJlcyAqIHNmX2dldF9mcmFt ZV9zaXplKGlwX2RhdGEtJmd0O3NmKTs8YnI+DQorIDxicj4NCistI2lmIExJQkFWQ09ERUNfVkVS U0lPTl9NQUpPUiAmZ3Q7PSA1Njxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGF2X2ZyYW1l X2ZyZWUoJmFtcDtmcmFtZSk7PGJyPg0KKy0jZWxzZTxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAg wqAgYXZjb2RlY19mcmVlX2ZyYW1lKCZhbXA7ZnJhbWUpOzxicj4NCistI2VuZGlmPGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIG91dHB1dC0mZ3Q7YnVmZmVyX3VzZWRfbGVuOzxi cj4NCivCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAvKiBUaGlzIHNob3VsZCBuZXZlciBn ZXQgaGVyZS4gKi88YnI+DQorQEAgLTQ1MywxMSArMzkyLDExIEBAIHN0YXRpYyBpbnQgZmZtcGVn X3JlYWQoc3RydWN0IGlucHV0X3BsdWdpbl9kYXRhICppcF9kYXRhLCBjaGFyICpidWZmZXIsIGlu dCBjb3VuPGJyPg0KK8KgIMKgIMKgIMKgaW50IG91dF9zaXplOzxicj4NCisgPGJyPg0KK8KgIMKg IMKgIMKgaWYgKG91dHB1dC0mZ3Q7YnVmZmVyX3VzZWRfbGVuID09IDApIHs8YnI+DQorLcKgIMKg IMKgIMKgIMKgIMKgIMKgIHJjID0gZmZtcGVnX2ZpbGxfYnVmZmVyKGlwX2RhdGEsIHByaXYtJmd0 O2lucHV0X2NvbnRleHQsIHByaXYtJmd0O2NvZGVjX2NvbnRleHQsPGJyPg0KKyvCoCDCoCDCoCDC oCDCoCDCoCDCoCByYyA9IGZmbXBlZ19maWxsX2J1ZmZlcihpcF9kYXRhLDxicj4NCisrwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcHJpdi0mZ3Q7aW5wdXRfY29u dGV4dCwgcHJpdi0mZ3Q7Y29kZWNfY29udGV4dCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwcml2LSZndDtpbnB1dCwgcHJpdi0mZ3Q7b3V0cHV0 LCBwcml2LSZndDtzd3IpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHJjICZsdDs9 IDApIHs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChyYyAmbHQ7PSAwKTxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiByYzs8YnI+DQorLcKgIMKg IMKgIMKgIMKgIMKgIMKgIH08YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKgIMKgb3V0 X3NpemUgPSBtaW5faShvdXRwdXQtJmd0O2J1ZmZlcl91c2VkX2xlbiwgY291bnQpOzxicj4NCivC oCDCoCDCoCDCoG1lbWNweShidWZmZXIsIG91dHB1dC0mZ3Q7YnVmZmVyX3Bvcywgb3V0X3NpemUp Ozxicj4NCitAQCAtNDc3LDYgKzQxNiw3IEBAIHN0YXRpYyBpbnQgZmZtcGVnX3NlZWsoc3RydWN0 IGlucHV0X3BsdWdpbl9kYXRhICppcF9kYXRhLCBkb3VibGUgb2Zmc2V0KTxicj4NCivCoCDCoCDC oCDCoGludDY0X3QgdHMgPSBhdl9yZXNjYWxlKG9mZnNldCwgc3QtJmd0O3RpbWVfYmFzZS5kZW4s IHN0LSZndDt0aW1lX2Jhc2UubnVtKTs8YnI+DQorIDxicj4NCivCoCDCoCDCoCDCoGF2Y29kZWNf Zmx1c2hfYnVmZmVycyhwcml2LSZndDtjb2RlY19jb250ZXh0KTs8YnI+DQorK8KgIMKgIMKgIC8q IFRPRE86IGFsc28gZmx1c2ggc3dyZXNhbXBsZSBidWZmZXJzICovPGJyPg0KK8KgIMKgIMKgIMKg LyogRm9yY2UgcmVhZGluZyBhIG5ldyBwYWNrZXQgaW4gbmV4dCBmZm1wZWdfZmlsbF9idWZmZXIo KS4gKi88YnI+DQorwqAgwqAgwqAgwqBwcml2LSZndDtpbnB1dC0mZ3Q7Y3Vycl9wa3Rfc2l6ZSA9 IDA7PGJyPg0KKyA8YnI+DQorQEAgLTUwMSw3ICs0NDEsOCBAQCBzdGF0aWMgdm9pZCBmZm1wZWdf cmVhZF9tZXRhZGF0YShzdHJ1Y3QgZ3Jvd2luZ19rZXl2YWxzICpjLCBBVkRpY3Rpb25hcnkgKm1l dGFkYTxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorIH08YnI+DQorIDxicj4NCistc3RhdGljIGlu dCBmZm1wZWdfcmVhZF9jb21tZW50cyhzdHJ1Y3QgaW5wdXRfcGx1Z2luX2RhdGEgKmlwX2RhdGEs IHN0cnVjdCBrZXl2YWwgKipjb21tZW50cyk8YnI+DQorK3N0YXRpYyBpbnQgZmZtcGVnX3JlYWRf Y29tbWVudHMoc3RydWN0IGlucHV0X3BsdWdpbl9kYXRhICppcF9kYXRhLDxicj4NCisrwqAgwqAg wqAgwqAgwqAgwqAgwqAgc3RydWN0IGtleXZhbCAqKmNvbW1lbnRzKTxicj4NCisgezxicj4NCivC oCDCoCDCoCDCoHN0cnVjdCBmZm1wZWdfcHJpdmF0ZSAqcHJpdiA9IGlwX2RhdGEtJmd0O3ByaXZh dGU7PGJyPg0KK8KgIMKgIMKgIMKgQVZGb3JtYXRDb250ZXh0ICppYyA9IHByaXYtJmd0O2lucHV0 X2NvbnRleHQ7PGJyPg0KK0BAIC01MzgsMTEgKzQ3OSw3IEBAIHN0YXRpYyBsb25nIGZmbXBlZ19j dXJyZW50X2JpdHJhdGUoc3RydWN0IGlucHV0X3BsdWdpbl9kYXRhICppcF9kYXRhKTxicj4NCivC oCDCoCDCoCDCoEFWU3RyZWFtICpzdCA9IHByaXYtJmd0O2lucHV0X2NvbnRleHQtJmd0O3N0cmVh bXNbcHJpdi0mZ3Q7aW5wdXQtJmd0O3N0cmVhbV9pbmRleF07PGJyPg0KK8KgIMKgIMKgIMKgbG9u ZyBiaXRyYXRlID0gLTE7PGJyPg0KK8KgIMKgIMKgIMKgLyogYXBlIGNvZGVjIHJldHVybnMgc2ls bHkgbnVtYmVycyAqLzxicj4NCistI2lmIExJQkFWQ09ERUNfVkVSU0lPTl9NQUpPUiAmZ3Q7PSA1 NTxicj4NCivCoCDCoCDCoCDCoGlmIChwcml2LSZndDtjb2RlYy0mZ3Q7aWQgPT0gQVZfQ09ERUNf SURfQVBFKTxicj4NCistI2Vsc2U8YnI+DQorLcKgIMKgIMKgIGlmIChwcml2LSZndDtjb2RlYy0m Z3Q7aWQgPT0gQ09ERUNfSURfQVBFKTxicj4NCistI2VuZGlmPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgcmV0dXJuIC0xOzxicj4NCivCoCDCoCDCoCDCoGlmIChwcml2LSZndDtpbnB1dC0m Z3Q7Y3Vycl9kdXJhdGlvbiAmZ3Q7IDApIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBk b3VibGUgc2Vjb25kcyA9IHByaXYtJmd0O2lucHV0LSZndDtjdXJyX2R1cmF0aW9uICogYXZfcTJk KHN0LSZndDt0aW1lX2Jhc2UpOzxicj4NCis8YnI+DQorRnJvbSBlMWEyMzc0YTYwYTQxOTg3Zjk1 YzdkODkyZWJjMWIxNTBkZjdhY2IxIE1vbiBTZXAgMTcgMDA6MDA6MDAgMjAwMTxicj4NCitGcm9t OiBpaHkxMjMgJmx0OzxhIGhyZWY9Im1haWx0bzphbGFkaW5hbmRyZXl5QGdtYWlsLmNvbSIgdGFy Z2V0PSJfYmxhbmsiPmFsYWRpbmFuZHJleXlAZ21haWwuY29tPC9hPiZndDs8YnI+DQorRGF0ZTog U3VuLCAxNyBBdWcgMjAyNSAwNDowNTozNiArMDMwMDxicj4NCitTdWJqZWN0OiBbUEFUQ0ggMDQv MTJdIGlwL2ZmbXBlZzogbWFqb3IgcmVmYWN0b3I8YnI+DQorPGJyPg0KKy0tLTxicj4NCisgaXAv ZmZtcGVnLmMgfCA2NDMgKysrKysrKysrKysrKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLTxicj4NCisgMSBmaWxlIGNoYW5nZWQsIDMzMCBpbnNlcnRpb25zKCspLCAzMTMg ZGVsZXRpb25zKC0pPGJyPg0KKzxicj4NCitkaWZmIC0tZ2l0wqAgaXAvZmZtcGVnLmPCoCBpcC9m Zm1wZWcuYzxicj4NCitpbmRleCBmNmExMWY0NTAuLjQyZjYzMGVlNyAxMDA2NDQ8YnI+DQorLS0t wqAgaXAvZmZtcGVnLmM8YnI+DQorKysrwqAgaXAvZmZtcGVnLmM8YnI+DQorQEAgLTM1LDg0ICsz NSwzMiBAQDxicj4NCisgI2luY2x1ZGUgJmx0O2xpYmF2dXRpbC9tYXRoZW1hdGljcy5oJmd0Ozxi cj4NCisgI2VuZGlmPGJyPg0KKyA8YnI+DQorLSNpZm5kZWYgQVZDT0RFQ19NQVhfQVVESU9fRlJB TUVfU0laRTxicj4NCistI2RlZmluZSBBVkNPREVDX01BWF9BVURJT19GUkFNRV9TSVpFIDE5MjAw MDxicj4NCistI2VuZGlmPGJyPg0KKytzdHJ1Y3QgZmZtcGVnX3ByaXZhdGUgezxicj4NCisrwqAg wqAgwqAgQVZDb2RlY0NvbnRleHQgKmNvZGVjX2N0eDs8YnI+DQorK8KgIMKgIMKgIEFWRm9ybWF0 Q29udGV4dCAqZm9ybWF0X2N0eDs8YnI+DQorK8KgIMKgIMKgIEFWQ29kZWMgY29uc3QgKmNvZGVj Ozxicj4NCisrwqAgwqAgwqAgU3dyQ29udGV4dCAqc3dyOzxicj4NCisrwqAgwqAgwqAgaW50IHN0 cmVhbV9pbmRleDs8YnI+DQorIDxicj4NCistc3RydWN0IGZmbXBlZ19pbnB1dCB7PGJyPg0KKy3C oCDCoCDCoCBBVlBhY2tldCBwa3Q7PGJyPg0KKy3CoCDCoCDCoCBpbnQgY3Vycl9wa3Rfc2l6ZTs8 YnI+DQorK8KgIMKgIMKgIEFWUGFja2V0ICpwa3Q7PGJyPg0KKyvCoCDCoCDCoCBBVkZyYW1lICpm cmFtZTs8YnI+DQorwqAgwqAgwqAgwqBpbnQ2NF90IHNlZWtfdHM7PGJyPg0KK8KgIMKgIMKgIMKg aW50NjRfdCBwcmV2X2ZyYW1lX2VuZDs8YnI+DQorLcKgIMKgIMKgIGludCBzdHJlYW1faW5kZXg7 PGJyPg0KKyA8YnI+DQorK8KgIMKgIMKgIC8qIEEgYnVmZmVyIHRvIGhvbGQgc3dyX2NvbnZlcnQo KS1lZCBzYW1wbGVzICovPGJyPg0KKyvCoCDCoCDCoCBBVkZyYW1lICpzd3JfZnJhbWU7PGJyPg0K KyvCoCDCoCDCoCBpbnQgc3dyX2ZyYW1lX3N0YXJ0Ozxicj4NCisrPGJyPg0KKyvCoCDCoCDCoCAv KiBCaXRyYXRlIGVzdGltYXRpb24gKi88YnI+DQorwqAgwqAgwqAgwqB1bnNpZ25lZCBsb25nIGN1 cnJfc2l6ZTs8YnI+DQorwqAgwqAgwqAgwqB1bnNpZ25lZCBsb25nIGN1cnJfZHVyYXRpb247PGJy Pg0KKyB9Ozxicj4NCisgPGJyPg0KKy1zdHJ1Y3QgZmZtcGVnX291dHB1dCB7PGJyPg0KKy3CoCDC oCDCoCB1aW50OF90ICpidWZmZXI7PGJyPg0KKy3CoCDCoCDCoCB1aW50OF90ICpidWZmZXJfbWFs bG9jOzxicj4NCistwqAgwqAgwqAgdWludDhfdCAqYnVmZmVyX3BvczvCoCDCoCAvKiBjdXJyZW50 IGJ1ZmZlciBwb3NpdGlvbiAqLzxicj4NCistwqAgwqAgwqAgaW50IGJ1ZmZlcl91c2VkX2xlbjs8 YnI+DQorLX07PGJyPg0KKy08YnI+DQorLXN0cnVjdCBmZm1wZWdfcHJpdmF0ZSB7PGJyPg0KKy3C oCDCoCDCoCBBVkNvZGVjQ29udGV4dCAqY29kZWNfY29udGV4dDs8YnI+DQorLcKgIMKgIMKgIEFW Rm9ybWF0Q29udGV4dCAqaW5wdXRfY29udGV4dDs8YnI+DQorLcKgIMKgIMKgIEFWQ29kZWMgY29u c3QgKmNvZGVjOzxicj4NCistwqAgwqAgwqAgU3dyQ29udGV4dCAqc3dyOzxicj4NCistPGJyPg0K Ky3CoCDCoCDCoCBzdHJ1Y3QgZmZtcGVnX2lucHV0ICppbnB1dDs8YnI+DQorLcKgIMKgIMKgIHN0 cnVjdCBmZm1wZWdfb3V0cHV0ICpvdXRwdXQ7PGJyPg0KKy19Ozxicj4NCistPGJyPg0KKy1zdGF0 aWMgc3RydWN0IGZmbXBlZ19pbnB1dCAqZmZtcGVnX2lucHV0X2NyZWF0ZSh2b2lkKTxicj4NCist ezxicj4NCistwqAgwqAgwqAgc3RydWN0IGZmbXBlZ19pbnB1dCAqaW5wdXQgPSB4bmV3KHN0cnVj dCBmZm1wZWdfaW5wdXQsIDEpOzxicj4NCistPGJyPg0KKy3CoCDCoCDCoCBpZiAoYXZfbmV3X3Bh Y2tldCgmYW1wO2lucHV0LSZndDtwa3QsIDApICE9IDApIHs8YnI+DQorLcKgIMKgIMKgIMKgIMKg IMKgIMKgIGZyZWUoaW5wdXQpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIE5V TEw7PGJyPg0KKy3CoCDCoCDCoCB9PGJyPg0KKy3CoCDCoCDCoCBpbnB1dC0mZ3Q7Y3Vycl9wa3Rf c2l6ZSA9IDA7PGJyPg0KKy3CoCDCoCDCoCBpbnB1dC0mZ3Q7c2Vla190cyA9IC0xOzxicj4NCist wqAgwqAgwqAgaW5wdXQtJmd0O3ByZXZfZnJhbWVfZW5kID0gLTE7PGJyPg0KKy3CoCDCoCDCoCBy ZXR1cm4gaW5wdXQ7PGJyPg0KKy19PGJyPg0KKy08YnI+DQorLXN0YXRpYyB2b2lkIGZmbXBlZ19p bnB1dF9mcmVlKHN0cnVjdCBmZm1wZWdfaW5wdXQgKmlucHV0KTxicj4NCistezxicj4NCistwqAg wqAgwqAgYXZfcGFja2V0X3VucmVmKCZhbXA7aW5wdXQtJmd0O3BrdCk7PGJyPg0KKy3CoCDCoCDC oCBmcmVlKGlucHV0KTs8YnI+DQorLX08YnI+DQorLTxicj4NCistc3RhdGljIHN0cnVjdCBmZm1w ZWdfb3V0cHV0ICpmZm1wZWdfb3V0cHV0X2NyZWF0ZSh2b2lkKTxicj4NCistezxicj4NCistwqAg wqAgwqAgc3RydWN0IGZmbXBlZ19vdXRwdXQgKm91dHB1dCA9IHhuZXcoc3RydWN0IGZmbXBlZ19v dXRwdXQsIDEpOzxicj4NCistPGJyPg0KKy3CoCDCoCDCoCBvdXRwdXQtJmd0O2J1ZmZlcl9tYWxs b2MgPSB4bmV3KHVpbnQ4X3QsIEFWQ09ERUNfTUFYX0FVRElPX0ZSQU1FX1NJWkUgKyAxNSk7PGJy Pg0KKy3CoCDCoCDCoCBvdXRwdXQtJmd0O2J1ZmZlciA9IG91dHB1dC0mZ3Q7YnVmZmVyX21hbGxv Yzs8YnI+DQorLcKgIMKgIMKgIC8qIGFsaWduIHRvIDE2IGJ5dGVzIHNvIGF2Y29kZWMgY2FuIFNT RS9BbHRpdmVjL2V0YyAqLzxicj4NCistwqAgwqAgwqAgd2hpbGUgKChpbnRwdHJfdCkgb3V0cHV0 LSZndDtidWZmZXIgJSAxNik8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIG91dHB1dC0mZ3Q7 YnVmZmVyICs9IDE7PGJyPg0KKy3CoCDCoCDCoCBvdXRwdXQtJmd0O2J1ZmZlcl9wb3MgPSBvdXRw dXQtJmd0O2J1ZmZlcjs8YnI+DQorLcKgIMKgIMKgIG91dHB1dC0mZ3Q7YnVmZmVyX3VzZWRfbGVu ID0gMDs8YnI+DQorLcKgIMKgIMKgIHJldHVybiBvdXRwdXQ7PGJyPg0KKy19PGJyPg0KKy08YnI+ DQorLXN0YXRpYyB2b2lkIGZmbXBlZ19vdXRwdXRfZnJlZShzdHJ1Y3QgZmZtcGVnX291dHB1dCAq b3V0cHV0KTxicj4NCistezxicj4NCistwqAgwqAgwqAgZnJlZShvdXRwdXQtJmd0O2J1ZmZlcl9t YWxsb2MpOzxicj4NCistwqAgwqAgwqAgb3V0cHV0LSZndDtidWZmZXJfbWFsbG9jID0gTlVMTDs8 YnI+DQorLcKgIMKgIMKgIG91dHB1dC0mZ3Q7YnVmZmVyID0gTlVMTDs8YnI+DQorLcKgIMKgIMKg IGZyZWUob3V0cHV0KTs8YnI+DQorLX08YnI+DQorLTxicj4NCistc3RhdGljIGlubGluZSB2b2lk IGZmbXBlZ19idWZmZXJfZmx1c2goc3RydWN0IGZmbXBlZ19vdXRwdXQgKm91dHB1dCk8YnI+DQor K3N0YXRpYyBjb25zdCBjaGFyICpmZm1wZWdfZXJybXNnKGludCBlcnIpPGJyPg0KKyB7PGJyPg0K Ky3CoCDCoCDCoCBvdXRwdXQtJmd0O2J1ZmZlcl9wb3MgPSBvdXRwdXQtJmd0O2J1ZmZlcjs8YnI+ DQorLcKgIMKgIMKgIG91dHB1dC0mZ3Q7YnVmZmVyX3VzZWRfbGVuID0gMDs8YnI+DQorK8KgIMKg IMKgIHN0YXRpYyBjaGFyIGVycnN0cltBVl9FUlJPUl9NQVhfU1RSSU5HX1NJWkVdOzxicj4NCisr wqAgwqAgwqAgYXZfc3RyZXJyb3IoZXJyLCBlcnJzdHIsIEFWX0VSUk9SX01BWF9TVFJJTkdfU0la RSk7PGJyPg0KKyvCoCDCoCDCoCByZXR1cm4gZXJyc3RyOzxicj4NCisgfTxicj4NCisgPGJyPg0K KyBzdGF0aWMgdm9pZCBmZm1wZWdfaW5pdCh2b2lkKTxicj4NCitAQCAtMTMyLDMwMyArODAsMzcy IEBAIHN0YXRpYyB2b2lkIGZmbXBlZ19pbml0KHZvaWQpPGJyPg0KKyAjZW5kaWY8YnI+DQorIH08 YnI+DQorIDxicj4NCistc3RhdGljIGludCBmZm1wZWdfb3BlbihzdHJ1Y3QgaW5wdXRfcGx1Z2lu X2RhdGEgKmlwX2RhdGEpPGJyPg0KKytzdGF0aWMgaW50IGZmbXBlZ19vcGVuX2lucHV0KHN0cnVj dCBpbnB1dF9wbHVnaW5fZGF0YSAqaXBfZGF0YSw8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKg IHN0cnVjdCBmZm1wZWdfcHJpdmF0ZSAqcHJpdik8YnI+DQorIHs8YnI+DQorLcKgIMKgIMKgIHN0 cnVjdCBmZm1wZWdfcHJpdmF0ZSAqcHJpdjs8YnI+DQorLcKgIMKgIMKgIGludCBlcnIgPSAwOzxi cj4NCistwqAgwqAgwqAgaW50IGk7PGJyPg0KKy3CoCDCoCDCoCBpbnQgc3RyZWFtX2luZGV4ID0g LTE7PGJyPg0KKy3CoCDCoCDCoCBpbnQgb3V0X3NhbXBsZV9yYXRlOzxicj4NCistwqAgwqAgwqAg QVZDb2RlYyBjb25zdCAqY29kZWM7PGJyPg0KKy3CoCDCoCDCoCBBVkNvZGVjQ29udGV4dCAqY2Mg PSBOVUxMOzxicj4NCivCoCDCoCDCoCDCoEFWRm9ybWF0Q29udGV4dCAqaWMgPSBOVUxMOzxicj4N CisrwqAgwqAgwqAgQVZDb2RlY0NvbnRleHQgKmNjID0gTlVMTDs8YnI+DQorwqAgwqAgwqAgwqBB VkNvZGVjUGFyYW1ldGVycyAqY3AgPSBOVUxMOzxicj4NCistwqAgwqAgwqAgU3dyQ29udGV4dCAq c3dyID0gTlVMTDs8YnI+DQorLTxicj4NCistwqAgwqAgwqAgZmZtcGVnX2luaXQoKTs8YnI+DQor K8KgIMKgIMKgIEFWQ29kZWMgY29uc3QgKmNvZGVjID0gTlVMTDs8YnI+DQorK8KgIMKgIMKgIGlu dCBzdHJlYW1faW5kZXggPSAtMTs8YnI+DQorIDxicj4NCistwqAgwqAgwqAgZXJyID0gYXZmb3Jt YXRfb3Blbl9pbnB1dCgmYW1wO2ljLCBpcF9kYXRhLSZndDtmaWxlbmFtZSwgTlVMTCwgTlVMTCk7 PGJyPg0KKy3CoCDCoCDCoCBpZiAoZXJyICZsdDsgMCkgezxicj4NCistwqAgwqAgwqAgwqAgwqAg wqAgwqAgZF9wcmludCgmcXVvdDthdl9vcGVuIGZhaWxlZDogJWRcbiZxdW90OywgZXJyKTs8YnI+ DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIHJldHVybiAtSVBfRVJST1JfRklMRV9GT1JNQVQ7PGJy Pg0KKyvCoCDCoCDCoCBpbnQgZXJyOzxicj4NCisrwqAgwqAgwqAgaW50IHJlcyA9IGF2Zm9ybWF0 X29wZW5faW5wdXQoJmFtcDtpYywgaXBfZGF0YS0mZ3Q7ZmlsZW5hbWUsIE5VTEwsIE5VTEwpOzxi cj4NCisrwqAgwqAgwqAgaWYgKHJlcyAmbHQ7IDApIHs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKg IMKgIGVyciA9IC1JUF9FUlJPUl9GSUxFX0ZPUk1BVDs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKg IMKgIGdvdG8gZXJyOzxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorIDxicj4NCistwqAgwqAgwqAg ZG8gezxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgZXJyID0gYXZmb3JtYXRfZmluZF9zdHJl YW1faW5mbyhpYywgTlVMTCk7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoZXJyICZs dDsgMCkgezxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZF9wcmludCgm cXVvdDt1bmFibGUgdG8gZmluZCBzdHJlYW0gaW5mbzogJWRcbiZxdW90OywgZXJyKTs8YnI+DQor LcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGVyciA9IC1JUF9FUlJPUl9GSUxFX0ZP Uk1BVDs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGJyZWFrOzxicj4N CistwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4NCistPGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDC oCDCoCBmb3IgKGkgPSAwOyBpICZsdDsgaWMtJmd0O25iX3N0cmVhbXM7IGkrKykgezxicj4NCist wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY3AgPSBpYy0mZ3Q7c3RyZWFtc1tpXS0m Z3Q7Y29kZWNwYXI7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAo Y3AtJmd0O2NvZGVjX3R5cGUgPT0gQVZNRURJQV9UWVBFX0FVRElPKSB7PGJyPg0KKy3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdHJlYW1faW5kZXggPSBpOzxi cj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYnJlYWs7 PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KKy3CoCDCoCDC oCDCoCDCoCDCoCDCoCB9PGJyPg0KKy08YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChz dHJlYW1faW5kZXggPT0gLTEpIHs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIGRfcHJpbnQoJnF1b3Q7Y291bGQgbm90IGZpbmQgYXVkaW8gc3RyZWFtXG4mcXVvdDspOzxi cj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZXJyID0gLUlQX0VSUk9SX0ZJ TEVfRk9STUFUOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYnJlYWs7 PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KKy08YnI+DQorLcKgIMKgIMKgIMKg IMKgIMKgIMKgIGNvZGVjID0gYXZjb2RlY19maW5kX2RlY29kZXIoY3AtJmd0O2NvZGVjX2lkKTs8 YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIGNjID0gYXZjb2RlY19hbGxvY19jb250ZXh0Myhj b2RlYyk7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCBhdmNvZGVjX3BhcmFtZXRlcnNfdG9f Y29udGV4dChjYywgY3ApOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKCFjb2RlYykg ezxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZF9wcmludCgmcXVvdDtj b2RlYyBub3QgZm91bmQ6ICVkLCAlc1xuJnF1b3Q7LCBjYy0mZ3Q7Y29kZWNfaWQsIGF2Y29kZWNf Z2V0X25hbWUoY2MtJmd0O2NvZGVjX2lkKSk7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBlcnIgPSAtSVBfRVJST1JfVU5TVVBQT1JURURfRklMRV9UWVBFOzxicj4NCist wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYnJlYWs7PGJyPg0KKy3CoCDCoCDCoCDC oCDCoCDCoCDCoCB9PGJyPg0KKyvCoCDCoCDCoCByZXMgPSBhdmZvcm1hdF9maW5kX3N0cmVhbV9p bmZvKGljLCBOVUxMKTs8YnI+DQorK8KgIMKgIMKgIGlmIChyZXMgJmx0OyAwKSB7PGJyPg0KKyvC oCDCoCDCoCDCoCDCoCDCoCDCoCBkX3ByaW50KCZxdW90O3VuYWJsZSB0byBmaW5kIHN0cmVhbSBp bmZvXG4mcXVvdDspOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgZXJyID0gLUlQX0VSUk9S X0ZJTEVfRk9STUFUOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgZ290byBlcnI7PGJyPg0K KyvCoCDCoCDCoCB9PGJyPg0KKyA8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChhdmNv ZGVjX29wZW4yKGNjLCBjb2RlYywgTlVMTCkgJmx0OyAwKSB7PGJyPg0KKy3CoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCBkX3ByaW50KCZxdW90O2NvdWxkIG5vdCBvcGVuIGNvZGVjOiAl ZCwgJXNcbiZxdW90OywgY2MtJmd0O2NvZGVjX2lkLCBhdmNvZGVjX2dldF9uYW1lKGNjLSZndDtj b2RlY19pZCkpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZXJyID0g LUlQX0VSUk9SX1VOU1VQUE9SVEVEX0ZJTEVfVFlQRTs8YnI+DQorK8KgIMKgIMKgIGZvciAoaW50 IGkgPSAwOyBpICZsdDsgaWMtJmd0O25iX3N0cmVhbXM7IGkrKykgezxicj4NCisrwqAgwqAgwqAg wqAgwqAgwqAgwqAgY3AgPSBpYy0mZ3Q7c3RyZWFtc1tpXS0mZ3Q7Y29kZWNwYXI7PGJyPg0KKyvC oCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoY3AtJmd0O2NvZGVjX3R5cGUgPT0gQVZNRURJQV9UWVBF X0FVRElPKSB7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdHJlYW1f aW5kZXggPSBpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGJyZWFr Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorK8KgIMKgIMKgIH08YnI+DQor IDxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgLyogV2UgYXNzdW1lIGJlbG93IHRoYXQgbm8g bW9yZSBlcnJvcnMgZm9sbG93LiAqLzxicj4NCistwqAgwqAgwqAgfSB3aGlsZSAoMCk7PGJyPg0K KyvCoCDCoCDCoCBpZiAoc3RyZWFtX2luZGV4ID09IC0xKSB7PGJyPg0KKyvCoCDCoCDCoCDCoCDC oCDCoCDCoCBkX3ByaW50KCZxdW90O2NvdWxkIG5vdCBmaW5kIGF1ZGlvIHN0cmVhbVxuJnF1b3Q7 KTs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIGVyciA9IC1JUF9FUlJPUl9GSUxFX0ZPUk1B VDs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIGdvdG8gZXJyX3NpbGVudDs8YnI+DQorK8Kg IMKgIMKgIH08YnI+DQorIDxicj4NCistwqAgwqAgwqAgaWYgKGVyciAmbHQ7IDApIHs8YnI+DQor LcKgIMKgIMKgIMKgIMKgIMKgIMKgIC8qIENsZWFuIHVwLsKgIGNjIGlzIG5ldmVyIG9wZW5lZCBh dCB0aGlzIHBvaW50LsKgIChTZWUgYWJvdmUgYXNzdW1wdGlvbi4pICovPGJyPg0KKy3CoCDCoCDC oCDCoCDCoCDCoCDCoCBhdmNvZGVjX2ZyZWVfY29udGV4dCgmYW1wO2NjKTs8YnI+DQorLcKgIMKg IMKgIMKgIMKgIMKgIMKgIGF2Zm9ybWF0X2Nsb3NlX2lucHV0KCZhbXA7aWMpOzxicj4NCistwqAg wqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIGVycjs8YnI+DQorK8KgIMKgIMKgIGNvZGVjID0gYXZj b2RlY19maW5kX2RlY29kZXIoY3AtJmd0O2NvZGVjX2lkKTs8YnI+DQorK8KgIMKgIMKgIGlmICgh Y29kZWMpIHs8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIGRfcHJpbnQoJnF1b3Q7Y29kZWMg KGlkOiAlZCwgbmFtZTogJXMpIG5vdCBmb3VuZFxuJnF1b3Q7LDxicj4NCisrwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY2MtJmd0O2NvZGVjX2lkLCBhdmNvZGVj X2dldF9uYW1lKGNjLSZndDtjb2RlY19pZCkpOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAg ZXJyID0gLUlQX0VSUk9SX1VOU1VQUE9SVEVEX0ZJTEVfVFlQRTs8YnI+DQorK8KgIMKgIMKgIMKg IMKgIMKgIMKgIGdvdG8gZXJyX3NpbGVudDs8YnI+DQorK8KgIMKgIMKgIH08YnI+DQorK8KgIMKg IMKgIGNjID0gYXZjb2RlY19hbGxvY19jb250ZXh0Myhjb2RlYyk7PGJyPg0KKyvCoCDCoCDCoCBh dmNvZGVjX3BhcmFtZXRlcnNfdG9fY29udGV4dChjYywgY3ApOzxicj4NCisrPGJyPg0KKyvCoCDC oCDCoCByZXMgPSBhdmNvZGVjX29wZW4yKGNjLCBjb2RlYywgTlVMTCk7PGJyPg0KKyvCoCDCoCDC oCBpZiAocmVzICZsdDsgMCkgezxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgZF9wcmludCgm cXVvdDtjb3VsZCBub3Qgb3BlbiBjb2RlYyAoaWQ6ICVkLCBuYW1lOiAlcylcbiZxdW90Oyw8YnI+ DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNjLSZndDtj b2RlY19pZCwgYXZjb2RlY19nZXRfbmFtZShjYy0mZ3Q7Y29kZWNfaWQpKTs8YnI+DQorK8KgIMKg IMKgIMKgIMKgIMKgIMKgIGVyciA9IC1JUF9FUlJPUl9VTlNVUFBPUlRFRF9GSUxFX1RZUEU7PGJy Pg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCBnb3RvIGVycjs8YnI+DQorwqAgwqAgwqAgwqB9PGJy Pg0KKyA8YnI+DQorLcKgIMKgIMKgIHByaXYgPSB4bmV3KHN0cnVjdCBmZm1wZWdfcHJpdmF0ZSwg MSk7PGJyPg0KKy3CoCDCoCDCoCBwcml2LSZndDtjb2RlY19jb250ZXh0ID0gY2M7PGJyPg0KKy3C oCDCoCDCoCBwcml2LSZndDtpbnB1dF9jb250ZXh0ID0gaWM7PGJyPg0KKyvCoCDCoCDCoCBwcml2 LSZndDtmb3JtYXRfY3R4ID0gaWM7PGJyPg0KKyvCoCDCoCDCoCBwcml2LSZndDtjb2RlY19jdHgg PSBjYzs8YnI+DQorwqAgwqAgwqAgwqBwcml2LSZndDtjb2RlYyA9IGNvZGVjOzxicj4NCistwqAg wqAgwqAgcHJpdi0mZ3Q7aW5wdXQgPSBmZm1wZWdfaW5wdXRfY3JlYXRlKCk7PGJyPg0KKy3CoCDC oCDCoCBpZiAocHJpdi0mZ3Q7aW5wdXQgPT0gTlVMTCkgezxicj4NCistwqAgwqAgwqAgwqAgwqAg wqAgwqAgYXZjb2RlY19jbG9zZShjYyk7PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCBhdmNv ZGVjX2ZyZWVfY29udGV4dCgmYW1wO2NjKTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIGF2 Zm9ybWF0X2Nsb3NlX2lucHV0KCZhbXA7aWMpOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAg ZnJlZShwcml2KTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIHJldHVybiAtSVBfRVJST1Jf SU5URVJOQUw7PGJyPg0KKyvCoCDCoCDCoCBwcml2LSZndDtzdHJlYW1faW5kZXggPSBzdHJlYW1f aW5kZXg7PGJyPg0KKyvCoCDCoCDCoCByZXR1cm4gMDs8YnI+DQorK2Vycjo8YnI+DQorK8KgIMKg IMKgIGRfcHJpbnQoJnF1b3Q7JXNcbiZxdW90OywgZmZtcGVnX2Vycm1zZyhyZXMpKTs8YnI+DQor K2Vycl9zaWxlbnQ6PGJyPg0KKyvCoCDCoCDCoCBhdmNvZGVjX2ZyZWVfY29udGV4dCgmYW1wO2Nj KTs8YnI+DQorK8KgIMKgIMKgIGF2Zm9ybWF0X2Nsb3NlX2lucHV0KCZhbXA7aWMpOzxicj4NCisr wqAgwqAgwqAgcmV0dXJuIGVycjs8YnI+DQorK308YnI+DQorKzxicj4NCisrc3RhdGljIHZvaWQg ZmZtcGVnX3NldF9zZl9hbmRfc3dyX29wdHMoU3dyQ29udGV4dCAqc3dyLCBBVkNvZGVjQ29udGV4 dCAqY2MsPGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCBzYW1wbGVfZm9ybWF0X3QgKnNmX291 dCwgZW51bSBBVlNhbXBsZUZvcm1hdCAqb3V0X3NhbXBsZV9mbXQpPGJyPg0KKyt7PGJyPg0KKyvC oCDCoCDCoCBpbnQgb3V0X3NhbXBsZV9yYXRlID0gbWluX3UoY2MtJmd0O3NhbXBsZV9yYXRlLCAz ODQwMDApOzxicj4NCisrwqAgwqAgwqAgc2FtcGxlX2Zvcm1hdF90IHNmID0gc2ZfcmF0ZShvdXRf c2FtcGxlX3JhdGUpIHwgc2ZfaG9zdF9lbmRpYW4oKTs8YnI+DQorK8KgIMKgIMKgIGF2X29wdF9z ZXRfaW50KHN3ciwgJnF1b3Q7aW5fc2FtcGxlX3JhdGUmcXVvdDssIGNjLSZndDtzYW1wbGVfcmF0 ZSwgMCk7PGJyPg0KKyvCoCDCoCDCoCBhdl9vcHRfc2V0X2ludChzd3IsICZxdW90O291dF9zYW1w bGVfcmF0ZSZxdW90Oywgb3V0X3NhbXBsZV9yYXRlLCAwKTs8YnI+DQorKzxicj4NCisrwqAgwqAg wqAgKm91dF9zYW1wbGVfZm10ID0gY2MtJmd0O3NhbXBsZV9mbXQ7PGJyPg0KKyvCoCDCoCDCoCBz d2l0Y2ggKCpvdXRfc2FtcGxlX2ZtdCkgezxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgY2Fz ZSBBVl9TQU1QTEVfRk1UX1U4Ojxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgc2YgfD0gc2ZfYml0cyg4KSB8IHNmX3NpZ25lZCgwKTs8YnI+DQorK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIGJyZWFrOzxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgY2Fz ZSBBVl9TQU1QTEVfRk1UX1MzMjo8YnI+DQorK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIHNmIHw9IHNmX2JpdHMoMzIpIHwgc2Zfc2lnbmVkKDEpOzxicj4NCisrwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgYnJlYWs7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCBk ZWZhdWx0Ojxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2YgfD0gc2Zf Yml0cygxNikgfCBzZl9zaWduZWQoMSk7PGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCAqb3V0X3NhbXBsZV9mbXQgPSBBVl9TQU1QTEVfRk1UX1MxNjs8YnI+DQorwqAgwqAg wqAgwqB9PGJyPg0KKy3CoCDCoCDCoCBwcml2LSZndDtpbnB1dC0mZ3Q7c3RyZWFtX2luZGV4ID0g c3RyZWFtX2luZGV4Ozxicj4NCistwqAgwqAgwqAgcHJpdi0mZ3Q7b3V0cHV0ID0gZmZtcGVnX291 dHB1dF9jcmVhdGUoKTs8YnI+DQorK8KgIMKgIMKgIGF2X29wdF9zZXRfc2FtcGxlX2ZtdChzd3Is ICZxdW90O2luX3NhbXBsZV9mbXQmcXVvdDssIGNjLSZndDtzYW1wbGVfZm10LCAwKTs8YnI+DQor K8KgIMKgIMKgIGF2X29wdF9zZXRfc2FtcGxlX2ZtdChzd3IsICZxdW90O291dF9zYW1wbGVfZm10 JnF1b3Q7LCAqb3V0X3NhbXBsZV9mbXQsIDApOzxicj4NCisgPGJyPg0KKy3CoCDCoCDCoCAvKiBQ cmVwYXJlIGZvciByZXNhbXBsaW5nLiAqLzxicj4NCistwqAgwqAgwqAgb3V0X3NhbXBsZV9yYXRl ID0gbWluX3UoY2MtJmd0O3NhbXBsZV9yYXRlLCAzODQwMDApOzxicj4NCistwqAgwqAgwqAgc3dy ID0gc3dyX2FsbG9jKCk7PGJyPg0KKyAjaWYgTElCQVZDT0RFQ19WRVJTSU9OX0lOVCAmZ3Q7PSBB Vl9WRVJTSU9OX0lOVCg1OSwgMjQsIDEwMCk8YnI+DQorK8KgIMKgIMKgIHNmIHw9IHNmX2NoYW5u ZWxzKGNjLSZndDtjaF9sYXlvdXQubmJfY2hhbm5lbHMpOzxicj4NCisrPGJyPg0KK8KgIMKgIMKg IMKgaWYgKGNjLSZndDtjaF9sYXlvdXQub3JkZXIgPT0gQVZfQ0hBTk5FTF9PUkRFUl9VTlNQRUMp PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYXZfY2hhbm5lbF9sYXlvdXRfZGVmYXVsdCgm YW1wO2NjLSZndDtjaF9sYXlvdXQsIGNjLSZndDtjaF9sYXlvdXQubmJfY2hhbm5lbHMpOzxicj4N CistwqAgwqAgwqAgYXZfb3B0X3NldF9jaGxheW91dChzd3IsICZxdW90O2luX2NobGF5b3V0JnF1 b3Q7LMKgIMKgJmFtcDtjYy0mZ3Q7Y2hfbGF5b3V0LCAwKTs8YnI+DQorLcKgIMKgIMKgIGF2X29w dF9zZXRfY2hsYXlvdXQoc3dyLCAmcXVvdDtvdXRfY2hsYXlvdXQmcXVvdDsswqAgJmFtcDtjYy0m Z3Q7Y2hfbGF5b3V0LCAwKTs8YnI+DQorK8KgIMKgIMKgIGF2X29wdF9zZXRfY2hsYXlvdXQoc3dy LCAmcXVvdDtpbl9jaGxheW91dCZxdW90OywgJmFtcDtjYy0mZ3Q7Y2hfbGF5b3V0LCAwKTs8YnI+ DQorK8KgIMKgIMKgIGF2X29wdF9zZXRfY2hsYXlvdXQoc3dyLCAmcXVvdDtvdXRfY2hsYXlvdXQm cXVvdDssICZhbXA7Y2MtJmd0O2NoX2xheW91dCwgMCk7PGJyPg0KKyAjZWxzZTxicj4NCistwqAg wqAgwqAgYXZfb3B0X3NldF9pbnQoc3dyLCAmcXVvdDtpbl9jaGFubmVsX2xheW91dCZxdW90OyzC oCBhdl9nZXRfZGVmYXVsdF9jaGFubmVsX2xheW91dChjYy0mZ3Q7Y2hhbm5lbHMpLCAwKTs8YnI+ DQorLcKgIMKgIMKgIGF2X29wdF9zZXRfaW50KHN3ciwgJnF1b3Q7b3V0X2NoYW5uZWxfbGF5b3V0 JnF1b3Q7LCBhdl9nZXRfZGVmYXVsdF9jaGFubmVsX2xheW91dChjYy0mZ3Q7Y2hhbm5lbHMpLCAw KTs8YnI+DQorK8KgIMKgIMKgIHNmIHw9IHNmX2NoYW5uZWxzKGNjLSZndDtjaGFubmVscyk7PGJy Pg0KKys8YnI+DQorK8KgIMKgIMKgIGF2X29wdF9zZXRfaW50KHN3ciwgJnF1b3Q7aW5fY2hhbm5l bF9sYXlvdXQmcXVvdDssPGJyPg0KKyvCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBh dl9nZXRfZGVmYXVsdF9jaGFubmVsX2xheW91dChjYy0mZ3Q7Y2hhbm5lbHMpLCAwKTs8YnI+DQor K8KgIMKgIMKgIGF2X29wdF9zZXRfaW50KHN3ciwgJnF1b3Q7b3V0X2NoYW5uZWxfbGF5b3V0JnF1 b3Q7LDxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYXZfZ2V0X2RlZmF1 bHRfY2hhbm5lbF9sYXlvdXQoY2MtJmd0O2NoYW5uZWxzKSwgMCk7PGJyPg0KKyAjZW5kaWY8YnI+ DQorLcKgIMKgIMKgIGF2X29wdF9zZXRfaW50KHN3ciwgJnF1b3Q7aW5fc2FtcGxlX3JhdGUmcXVv dDsswqAgwqAgwqBjYy0mZ3Q7c2FtcGxlX3JhdGUsIDApOzxicj4NCistwqAgwqAgwqAgYXZfb3B0 X3NldF9pbnQoc3dyLCAmcXVvdDtvdXRfc2FtcGxlX3JhdGUmcXVvdDsswqAgwqAgb3V0X3NhbXBs ZV9yYXRlLCAwKTs8YnI+DQorLcKgIMKgIMKgIGF2X29wdF9zZXRfc2FtcGxlX2ZtdChzd3IsICZx dW90O2luX3NhbXBsZV9mbXQmcXVvdDsswqAgY2MtJmd0O3NhbXBsZV9mbXQsIDApOzxicj4NCist wqAgwqAgwqAgcHJpdi0mZ3Q7c3dyID0gc3dyOzxicj4NCisgPGJyPg0KKy3CoCDCoCDCoCBpcF9k YXRhLSZndDtwcml2YXRlID0gcHJpdjs8YnI+DQorK8KgIMKgIMKgICpzZl9vdXQgPSBzZjs8YnI+ DQorK308YnI+DQorKzxicj4NCisrc3RhdGljIGludCBmZm1wZWdfaW5pdF9zd3JfZnJhbWUoc3Ry dWN0IGZmbXBlZ19wcml2YXRlICpwcml2LDxicj4NCisrwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2Ft cGxlX2Zvcm1hdF90IHNmLCBlbnVtIEFWU2FtcGxlRm9ybWF0IG91dF9zYW1wbGVfZm10KTxicj4N Cisrezxicj4NCisrwqAgwqAgwqAgQVZDb2RlY0NvbnRleHQgKmNjID0gcHJpdi0mZ3Q7Y29kZWNf Y3R4Ozxicj4NCisrwqAgwqAgwqAgQVZGcmFtZSAqZnJhbWUgPSBhdl9mcmFtZV9hbGxvYygpOzxi cj4NCisrPGJyPg0KKyAjaWYgTElCQVZDT0RFQ19WRVJTSU9OX0lOVCAmZ3Q7PSBBVl9WRVJTSU9O X0lOVCg1OSwgMjQsIDEwMCk8YnI+DQorLcKgIMKgIMKgIGlwX2RhdGEtJmd0O3NmID0gc2ZfcmF0 ZShvdXRfc2FtcGxlX3JhdGUpIHwgc2ZfY2hhbm5lbHMoY2MtJmd0O2NoX2xheW91dC5uYl9jaGFu bmVscyk7PGJyPg0KKyvCoCDCoCDCoCBhdl9jaGFubmVsX2xheW91dF9jb3B5KCZhbXA7ZnJhbWUt Jmd0O2NoX2xheW91dCwgJmFtcDtjYy0mZ3Q7Y2hfbGF5b3V0KTs8YnI+DQorICNlbHNlPGJyPg0K Ky3CoCDCoCDCoCBpcF9kYXRhLSZndDtzZiA9IHNmX3JhdGUob3V0X3NhbXBsZV9yYXRlKSB8IHNm X2NoYW5uZWxzKGNjLSZndDtjaGFubmVscyk7PGJyPg0KKyvCoCDCoCDCoCBmcmFtZS0mZ3Q7Y2hh bm5lbF9sYXlvdXQgPSBhdl9nZXRfZGVmYXVsdF9jaGFubmVsX2xheW91dChjYy0mZ3Q7Y2hhbm5l bHMpOzxicj4NCisgI2VuZGlmPGJyPg0KKy3CoCDCoCDCoCBzd2l0Y2ggKGNjLSZndDtzYW1wbGVf Zm10KSB7PGJyPg0KKy3CoCDCoCDCoCBjYXNlIEFWX1NBTVBMRV9GTVRfVTg6PGJyPg0KKy3CoCDC oCDCoCDCoCDCoCDCoCDCoCBpcF9kYXRhLSZndDtzZiB8PSBzZl9iaXRzKDgpIHwgc2Zfc2lnbmVk KDApOzxicj4NCistwqAgwqAgwqAgwqAgwqAgwqAgwqAgYXZfb3B0X3NldF9zYW1wbGVfZm10KHN3 ciwgJnF1b3Q7b3V0X3NhbXBsZV9mbXQmcXVvdDssIEFWX1NBTVBMRV9GTVRfVTgswqAgMCk7PGJy Pg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCBicmVhazs8YnI+DQorLcKgIMKgIMKgIGNhc2UgQVZf U0FNUExFX0ZNVF9TMzI6PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCBpcF9kYXRhLSZndDtz ZiB8PSBzZl9iaXRzKDMyKSB8IHNmX3NpZ25lZCgxKTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKg IMKgIGF2X29wdF9zZXRfc2FtcGxlX2ZtdChzd3IsICZxdW90O291dF9zYW1wbGVfZm10JnF1b3Q7 LCBBVl9TQU1QTEVfRk1UX1MzMizCoCAwKTs8YnI+DQorLcKgIMKgIMKgIMKgIMKgIMKgIMKgIGJy ZWFrOzxicj4NCistwqAgwqAgwqAgLyogQVZfU0FNUExFX0ZNVF9TMTYgKi88YnI+DQorLcKgIMKg IMKgIGRlZmF1bHQ6PGJyPg0KKy3CoCDCoCDCoCDCoCDCoCDCoCDCoCBpcF9kYXRhLSZndDtzZiB8 PSBzZl9iaXRzKDE2KSB8IHNmX3NpZ25lZCgxKTs8YnI+DQoqKiogODc4IExJTkVTIFNLSVBQRUQg KioqPGJyPg0KPC9ibG9ja3F1b3RlPjwvZGl2PjxkaXY+PGJyIGNsZWFyPSJhbGwiPjwvZGl2Pjxi cj48c3BhbiBjbGFzcz0iZ21haWxfc2lnbmF0dXJlX3ByZWZpeCI+LS0gPC9zcGFuPjxicj48ZGl2 IGRpcj0ibHRyIiBjbGFzcz0iZ21haWxfc2lnbmF0dXJlIj48ZGl2IGRpcj0ibHRyIj48ZGl2Pjxm b250IGNvbG9yPSIjODg4ODg4Ij5OdW5vIFRlaXhlaXJhPC9mb250PjwvZGl2PjxkaXY+PGRpdj48 Zm9udCBjb2xvcj0iIzg4ODg4OCI+DQpGcmVlQlNEIFVOSVg6wqAgJmx0O2VkdWFyZG9ARnJlZUJT RC5vcmcmZ3Q7wqAgwqBXZWI6wqAgPGEgaHJlZj0iaHR0cHM6Ly9GcmVlQlNELm9yZyIgcmVsPSJu b3JlZmVycmVyIiB0YXJnZXQ9Il9ibGFuayI+aHR0cHM6Ly9GcmVlQlNELm9yZzwvYT48YnI+PC9m b250PjwvZGl2PjwvZGl2PjwvZGl2PjwvZGl2Pg0K --0000000000005cac46063d21764e--