LyoKICogRE8gTk9UIEFMVEVSIE9SIFJFTU9WRSBDT1BZUklHSFQgTk9USUNFUyBPUiBUSElTIEZJTEUgSEVBREVSLgogKgogKiBUaGlzIGNvZGUgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdAogKiB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMiBvbmx5LCBhcwogKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4gIE9yYWNsZSBkZXNpZ25hdGVzIHRoaXMKICogcGFydGljdWxhciBmaWxlIGFzIHN1YmplY3QgdG8gdGhlICJDbGFzc3BhdGgiIGV4Y2VwdGlvbiBhcyBwcm92aWRlZAogKiBieSBPcmFjbGUgaW4gdGhlIExJQ0VOU0UgZmlsZSB0aGF0IGFjY29tcGFuaWVkIHRoaXMgY29kZS4KICoKICogVGhpcyBjb2RlIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUCiAqIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWSBvcgogKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKICogdmVyc2lvbiAyIGZvciBtb3JlIGRldGFpbHMgKGEgY29weSBpcyBpbmNsdWRlZCBpbiB0aGUgTElDRU5TRSBmaWxlIHRoYXQKICogYWNjb21wYW5pZWQgdGhpcyBjb2RlKS4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvbgogKiAyIGFsb25nIHdpdGggdGhpcyB3b3JrOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sCiAqIEluYy4sIDUxIEZyYW5rbGluIFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxIFVTQS4KICoKICogUGxlYXNlIGNvbnRhY3QgT3JhY2xlLCA1MDAgT3JhY2xlIFBhcmt3YXksIFJlZHdvb2QgU2hvcmVzLCBDQSA5NDA2NSBVU0EKICogb3IgdmlzaXQgd3d3Lm9yYWNsZS5jb20gaWYgeW91IG5lZWQgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBvciBoYXZlIGFueQogKiBxdWVzdGlvbnMuCiAqLwoKLy8gVGhpcyBmaWxlIGlzIGF2YWlsYWJsZSB1bmRlciBhbmQgZ292ZXJuZWQgYnkgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYwovLyBMaWNlbnNlIHZlcnNpb24gMiBvbmx5LCBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KLy8gSG93ZXZlciwgdGhlIGZvbGxvd2luZyBub3RpY2UgYWNjb21wYW5pZWQgdGhlIG9yaWdpbmFsIHZlcnNpb24gb2YgdGhpcwovLyBmaWxlOgovLwovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLwovLyAgTGl0dGxlIENvbG9yIE1hbmFnZW1lbnQgU3lzdGVtCi8vICBDb3B5cmlnaHQgKGMpIDE5OTgtMjAxNCBNYXJ0aSBNYXJpYSBTYWd1ZXIKLy8KLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nCi8vIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUiKSwKLy8gdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbgovLyB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwKLy8gYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlCi8vIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6Ci8vCi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluCi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLgovLwovLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwKLy8gRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPCi8vIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5ECi8vIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUKLy8gTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTgovLyBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04KLy8gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCi8vCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vCgojaW5jbHVkZSAibGNtczJfaW50ZXJuYWwuaCIKCi8vIFZpcnR1YWwgKGJ1aWx0LWluKSBwcm9maWxlcwovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKc3RhdGljCmNtc0Jvb2wgU2V0VGV4dFRhZ3MoY21zSFBST0ZJTEUgaFByb2ZpbGUsIGNvbnN0IHdjaGFyX3QqIERlc2NyaXB0aW9uKQp7CiAgICBjbXNNTFUgKkRlc2NyaXB0aW9uTUxVLCAqQ29weXJpZ2h0TUxVOwogICAgY21zQm9vbCAgcmMgPSBGQUxTRTsKICAgIGNtc0NvbnRleHQgQ29udGV4dElEID0gY21zR2V0UHJvZmlsZUNvbnRleHRJRChoUHJvZmlsZSk7CgogICAgRGVzY3JpcHRpb25NTFUgID0gY21zTUxVYWxsb2MoQ29udGV4dElELCAxKTsKICAgIENvcHlyaWdodE1MVSAgICA9IGNtc01MVWFsbG9jKENvbnRleHRJRCwgMSk7CgogICAgaWYgKERlc2NyaXB0aW9uTUxVID09IE5VTEwgfHwgQ29weXJpZ2h0TUxVID09IE5VTEwpIGdvdG8gRXJyb3I7CgogICAgaWYgKCFjbXNNTFVzZXRXaWRlKERlc2NyaXB0aW9uTUxVLCAgImVuIiwgIlVTIiwgRGVzY3JpcHRpb24pKSBnb3RvIEVycm9yOwogICAgaWYgKCFjbXNNTFVzZXRXaWRlKENvcHlyaWdodE1MVSwgICAgImVuIiwgIlVTIiwgTCJObyBjb3B5cmlnaHQsIHVzZSBmcmVlbHkiKSkgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1dyaXRlVGFnKGhQcm9maWxlLCBjbXNTaWdQcm9maWxlRGVzY3JpcHRpb25UYWcsICBEZXNjcmlwdGlvbk1MVSkpIGdvdG8gRXJyb3I7CiAgICBpZiAoIWNtc1dyaXRlVGFnKGhQcm9maWxlLCBjbXNTaWdDb3B5cmlnaHRUYWcsICAgICAgICAgICBDb3B5cmlnaHRNTFUpKSBnb3RvIEVycm9yOwoKICAgIHJjID0gVFJVRTsKCkVycm9yOgoKICAgIGlmIChEZXNjcmlwdGlvbk1MVSkKICAgICAgICBjbXNNTFVmcmVlKERlc2NyaXB0aW9uTUxVKTsKICAgIGlmIChDb3B5cmlnaHRNTFUpCiAgICAgICAgY21zTUxVZnJlZShDb3B5cmlnaHRNTFUpOwogICAgcmV0dXJuIHJjOwp9CgoKc3RhdGljCmNtc0Jvb2wgIFNldFNlcURlc2NUYWcoY21zSFBST0ZJTEUgaFByb2ZpbGUsIGNvbnN0IGNoYXIqIE1vZGVsKQp7CiAgICBjbXNCb29sICByYyA9IEZBTFNFOwogICAgY21zQ29udGV4dCBDb250ZXh0SUQgPSBjbXNHZXRQcm9maWxlQ29udGV4dElEKGhQcm9maWxlKTsKICAgIGNtc1NFUSogU2VxID0gY21zQWxsb2NQcm9maWxlU2VxdWVuY2VEZXNjcmlwdGlvbihDb250ZXh0SUQsIDEpOwoKICAgIGlmIChTZXEgPT0gTlVMTCkgcmV0dXJuIEZBTFNFOwoKICAgIFNlcS0+c2VxWzBdLmRldmljZU1mZyA9IChjbXNTaWduYXR1cmUpIDA7CiAgICBTZXEtPnNlcVswXS5kZXZpY2VNb2RlbCA9IChjbXNTaWduYXR1cmUpIDA7CgojaWZkZWYgQ01TX0RPTlRfVVNFX0lOVDY0CiAgICBTZXEtPnNlcVswXS5hdHRyaWJ1dGVzWzBdID0gMDsKICAgIFNlcS0+c2VxWzBdLmF0dHJpYnV0ZXNbMV0gPSAwOwojZWxzZQogICAgU2VxLT5zZXFbMF0uYXR0cmlidXRlcyA9IDA7CiNlbmRpZgoKICAgIFNlcS0+c2VxWzBdLnRlY2hub2xvZ3kgPSAoY21zVGVjaG5vbG9neVNpZ25hdHVyZSkgMDsKCiAgICBjbXNNTFVzZXRBU0NJSSggU2VxLT5zZXFbMF0uTWFudWZhY3R1cmVyLCBjbXNOb0xhbmd1YWdlLCBjbXNOb0NvdW50cnksICJMaXR0bGUgQ01TIik7CiAgICBjbXNNTFVzZXRBU0NJSSggU2VxLT5zZXFbMF0uTW9kZWwsICAgICAgICBjbXNOb0xhbmd1YWdlLCBjbXNOb0NvdW50cnksIE1vZGVsKTsKCiAgICBpZiAoIV9jbXNXcml0ZVByb2ZpbGVTZXF1ZW5jZShoUHJvZmlsZSwgU2VxKSkgZ290byBFcnJvcjsKCiAgICByYyA9IFRSVUU7CgpFcnJvcjoKICAgIGlmIChTZXEpCiAgICAgICAgY21zRnJlZVByb2ZpbGVTZXF1ZW5jZURlc2NyaXB0aW9uKFNlcSk7CgogICAgcmV0dXJuIHJjOwp9CgoKCi8vIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyBhIHByb2ZpbGUgYmFzZWQgb24gV2hpdGUgcG9pbnQsIHByaW1hcmllcyBhbmQKLy8gdHJhbnNmZXIgZnVuY3Rpb25zLgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlUkdCUHJvZmlsZVRIUihjbXNDb250ZXh0IENvbnRleHRJRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY21zQ0lFeHlZKiBXaGl0ZVBvaW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbXNDSUV4eVlUUklQTEUqIFByaW1hcmllcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zVG9uZUN1cnZlKiBjb25zdCBUcmFuc2ZlckZ1bmN0aW9uWzNdKQp7CiAgICBjbXNIUFJPRklMRSBoSUNDOwogICAgY21zTUFUMyBNQ29sb3JhbnRzOwogICAgY21zQ0lFWFlaVFJJUExFIENvbG9yYW50czsKICAgIGNtc0NJRXh5WSBNYXhXaGl0ZTsKICAgIGNtc01BVDMgQ0hBRDsKICAgIGNtc0NJRVhZWiBXaGl0ZVBvaW50WFlaOwoKICAgIGhJQ0MgPSBjbXNDcmVhdGVQcm9maWxlUGxhY2Vob2xkZXIoQ29udGV4dElEKTsKICAgIGlmICghaElDQykgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbid0IGFsbG9jYXRlCiAgICAgICAgcmV0dXJuIE5VTEw7CgogICAgY21zU2V0UHJvZmlsZVZlcnNpb24oaElDQywgNC4zKTsKCiAgICBjbXNTZXREZXZpY2VDbGFzcyhoSUNDLCAgICAgIGNtc1NpZ0Rpc3BsYXlDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhJQ0MsICAgICAgIGNtc1NpZ1JnYkRhdGEpOwogICAgY21zU2V0UENTKGhJQ0MsICAgICAgICAgICAgICBjbXNTaWdYWVpEYXRhKTsKCiAgICBjbXNTZXRIZWFkZXJSZW5kZXJpbmdJbnRlbnQoaElDQywgIElOVEVOVF9QRVJDRVBUVUFMKTsKCgogICAgLy8gSW1wbGVtZW50IHByb2ZpbGUgdXNpbmcgZm9sbG93aW5nIHRhZ3M6CiAgICAvLwogICAgLy8gIDEgY21zU2lnUHJvZmlsZURlc2NyaXB0aW9uVGFnCiAgICAvLyAgMiBjbXNTaWdNZWRpYVdoaXRlUG9pbnRUYWcKICAgIC8vICAzIGNtc1NpZ1JlZENvbG9yYW50VGFnCiAgICAvLyAgNCBjbXNTaWdHcmVlbkNvbG9yYW50VGFnCiAgICAvLyAgNSBjbXNTaWdCbHVlQ29sb3JhbnRUYWcKICAgIC8vICA2IGNtc1NpZ1JlZFRSQ1RhZwogICAgLy8gIDcgY21zU2lnR3JlZW5UUkNUYWcKICAgIC8vICA4IGNtc1NpZ0JsdWVUUkNUYWcKICAgIC8vICA5IENocm9tYXRpYyBhZGFwdGF0aW9uIFRhZwogICAgLy8gVGhpcyBjb25mb3JtcyBhIHN0YW5kYXJkIFJHQiBEaXNwbGF5UHJvZmlsZSBhcyBzYXlzIElDQywgYW5kIHRoZW4gSSBhZGQgKEFzIHBlciBhZGRlbmR1bSBJSSkKICAgIC8vIDEwIGNtc1NpZ0Nocm9tYXRpY2l0eVRhZwoKCiAgICBpZiAoIVNldFRleHRUYWdzKGhJQ0MsIEwiUkdCIGJ1aWx0LWluIikpIGdvdG8gRXJyb3I7CgogICAgaWYgKFdoaXRlUG9pbnQpIHsKCiAgICAgICAgaWYgKCFjbXNXcml0ZVRhZyhoSUNDLCBjbXNTaWdNZWRpYVdoaXRlUG9pbnRUYWcsIGNtc0Q1MF9YWVooKSkpIGdvdG8gRXJyb3I7CgogICAgICAgIGNtc3h5WTJYWVooJldoaXRlUG9pbnRYWVosIFdoaXRlUG9pbnQpOwogICAgICAgIF9jbXNBZGFwdGF0aW9uTWF0cml4KCZDSEFELCBOVUxMLCAmV2hpdGVQb2ludFhZWiwgY21zRDUwX1hZWigpKTsKCiAgICAgICAgLy8gVGhpcyBpcyBhIFY0IHRhZywgYnV0IG1hbnkgQ01NIGRvZXMgcmVhZCBhbmQgdW5kZXJzdGFuZCBpdCBubyBtYXR0ZXIgd2hpY2ggdmVyc2lvbgogICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnQ2hyb21hdGljQWRhcHRhdGlvblRhZywgKHZvaWQqKSAmQ0hBRCkpIGdvdG8gRXJyb3I7CiAgICB9CgogICAgaWYgKFdoaXRlUG9pbnQgJiYgUHJpbWFyaWVzKSB7CgogICAgICAgIE1heFdoaXRlLnggPSAgV2hpdGVQb2ludCAtPiB4OwogICAgICAgIE1heFdoaXRlLnkgPSAgV2hpdGVQb2ludCAtPiB5OwogICAgICAgIE1heFdoaXRlLlkgPSAgMS4wOwoKICAgICAgICBpZiAoIV9jbXNCdWlsZFJHQjJYWVp0cmFuc2Zlck1hdHJpeCgmTUNvbG9yYW50cywgJk1heFdoaXRlLCBQcmltYXJpZXMpKSBnb3RvIEVycm9yOwoKICAgICAgICBDb2xvcmFudHMuUmVkLlggICA9IE1Db2xvcmFudHMudlswXS5uWzBdOwogICAgICAgIENvbG9yYW50cy5SZWQuWSAgID0gTUNvbG9yYW50cy52WzFdLm5bMF07CiAgICAgICAgQ29sb3JhbnRzLlJlZC5aICAgPSBNQ29sb3JhbnRzLnZbMl0ublswXTsKCiAgICAgICAgQ29sb3JhbnRzLkdyZWVuLlggPSBNQ29sb3JhbnRzLnZbMF0ublsxXTsKICAgICAgICBDb2xvcmFudHMuR3JlZW4uWSA9IE1Db2xvcmFudHMudlsxXS5uWzFdOwogICAgICAgIENvbG9yYW50cy5HcmVlbi5aID0gTUNvbG9yYW50cy52WzJdLm5bMV07CgogICAgICAgIENvbG9yYW50cy5CbHVlLlggID0gTUNvbG9yYW50cy52WzBdLm5bMl07CiAgICAgICAgQ29sb3JhbnRzLkJsdWUuWSAgPSBNQ29sb3JhbnRzLnZbMV0ublsyXTsKICAgICAgICBDb2xvcmFudHMuQmx1ZS5aICA9IE1Db2xvcmFudHMudlsyXS5uWzJdOwoKICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ1JlZENvbG9yYW50VGFnLCAgICh2b2lkKikgJkNvbG9yYW50cy5SZWQpKSBnb3RvIEVycm9yOwogICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnQmx1ZUNvbG9yYW50VGFnLCAgKHZvaWQqKSAmQ29sb3JhbnRzLkJsdWUpKSBnb3RvIEVycm9yOwogICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnR3JlZW5Db2xvcmFudFRhZywgKHZvaWQqKSAmQ29sb3JhbnRzLkdyZWVuKSkgZ290byBFcnJvcjsKICAgIH0KCgogICAgaWYgKFRyYW5zZmVyRnVuY3Rpb24pIHsKCiAgICAgICAgLy8gVHJpZXMgdG8gbWluaW1pemUgc3BhY2UuIFRoYW5rcyB0byBSaWNoYXJkIEh1Z2hlcyBmb3IgdGhpcyBuaWNlIGlkZWEKICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ1JlZFRSQ1RhZywgICAodm9pZCopIFRyYW5zZmVyRnVuY3Rpb25bMF0pKSBnb3RvIEVycm9yOwoKICAgICAgICBpZiAoVHJhbnNmZXJGdW5jdGlvblsxXSA9PSBUcmFuc2ZlckZ1bmN0aW9uWzBdKSB7CgogICAgICAgICAgICBpZiAoIWNtc0xpbmtUYWcgKGhJQ0MsIGNtc1NpZ0dyZWVuVFJDVGFnLCBjbXNTaWdSZWRUUkNUYWcpKSBnb3RvIEVycm9yOwoKICAgICAgICB9IGVsc2UgewoKICAgICAgICAgICAgaWYgKCFjbXNXcml0ZVRhZyhoSUNDLCBjbXNTaWdHcmVlblRSQ1RhZywgKHZvaWQqKSBUcmFuc2ZlckZ1bmN0aW9uWzFdKSkgZ290byBFcnJvcjsKICAgICAgICB9CgogICAgICAgIGlmIChUcmFuc2ZlckZ1bmN0aW9uWzJdID09IFRyYW5zZmVyRnVuY3Rpb25bMF0pIHsKCiAgICAgICAgICAgIGlmICghY21zTGlua1RhZyAoaElDQywgY21zU2lnQmx1ZVRSQ1RhZywgY21zU2lnUmVkVFJDVGFnKSkgZ290byBFcnJvcjsKCiAgICAgICAgfSBlbHNlIHsKCiAgICAgICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnQmx1ZVRSQ1RhZywgKHZvaWQqKSBUcmFuc2ZlckZ1bmN0aW9uWzJdKSkgZ290byBFcnJvcjsKICAgICAgICB9CiAgICB9CgogICAgaWYgKFByaW1hcmllcykgewogICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnQ2hyb21hdGljaXR5VGFnLCAodm9pZCopIFByaW1hcmllcykpIGdvdG8gRXJyb3I7CiAgICB9CgoKICAgIHJldHVybiBoSUNDOwoKRXJyb3I6CiAgICBpZiAoaElDQykKICAgICAgICBjbXNDbG9zZVByb2ZpbGUoaElDQyk7CiAgICByZXR1cm4gTlVMTDsKfQoKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZVJHQlByb2ZpbGUoY29uc3QgY21zQ0lFeHlZKiBXaGl0ZVBvaW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbXNDSUV4eVlUUklQTEUqIFByaW1hcmllcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zVG9uZUN1cnZlKiBjb25zdCBUcmFuc2ZlckZ1bmN0aW9uWzNdKQp7CiAgICByZXR1cm4gY21zQ3JlYXRlUkdCUHJvZmlsZVRIUihOVUxMLCBXaGl0ZVBvaW50LCBQcmltYXJpZXMsIFRyYW5zZmVyRnVuY3Rpb24pOwp9CgoKCi8vIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyBhIHByb2ZpbGUgYmFzZWQgb24gV2hpdGUgcG9pbnQgYW5kIHRyYW5zZmVyIGZ1bmN0aW9uLgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlR3JheVByb2ZpbGVUSFIoY21zQ29udGV4dCBDb250ZXh0SUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbXNDSUV4eVkqIFdoaXRlUG9pbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbXNUb25lQ3VydmUqIFRyYW5zZmVyRnVuY3Rpb24pCnsKICAgIGNtc0hQUk9GSUxFIGhJQ0M7CiAgICBjbXNDSUVYWVogdG1wOwoKICAgIGhJQ0MgPSBjbXNDcmVhdGVQcm9maWxlUGxhY2Vob2xkZXIoQ29udGV4dElEKTsKICAgIGlmICghaElDQykgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbid0IGFsbG9jYXRlCiAgICAgICAgcmV0dXJuIE5VTEw7CgogICAgY21zU2V0UHJvZmlsZVZlcnNpb24oaElDQywgNC4zKTsKCiAgICBjbXNTZXREZXZpY2VDbGFzcyhoSUNDLCAgICAgIGNtc1NpZ0Rpc3BsYXlDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhJQ0MsICAgICAgIGNtc1NpZ0dyYXlEYXRhKTsKICAgIGNtc1NldFBDUyhoSUNDLCAgICAgICAgICAgICAgY21zU2lnWFlaRGF0YSk7CiAgICBjbXNTZXRIZWFkZXJSZW5kZXJpbmdJbnRlbnQoaElDQywgIElOVEVOVF9QRVJDRVBUVUFMKTsKCgogICAgLy8gSW1wbGVtZW50IHByb2ZpbGUgdXNpbmcgZm9sbG93aW5nIHRhZ3M6CiAgICAvLwogICAgLy8gIDEgY21zU2lnUHJvZmlsZURlc2NyaXB0aW9uVGFnCiAgICAvLyAgMiBjbXNTaWdNZWRpYVdoaXRlUG9pbnRUYWcKICAgIC8vICAzIGNtc1NpZ0dyYXlUUkNUYWcKCiAgICAvLyBUaGlzIGNvbmZvcm1zIGEgc3RhbmRhcmQgR3JheSBEaXNwbGF5UHJvZmlsZQoKICAgIC8vIEZpbGwtaW4gdGhlIHRhZ3MKCiAgICBpZiAoIVNldFRleHRUYWdzKGhJQ0MsIEwiZ3JheSBidWlsdC1pbiIpKSBnb3RvIEVycm9yOwoKCiAgICBpZiAoV2hpdGVQb2ludCkgewoKICAgICAgICBjbXN4eVkyWFlaKCZ0bXAsIFdoaXRlUG9pbnQpOwogICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnTWVkaWFXaGl0ZVBvaW50VGFnLCAodm9pZCopICZ0bXApKSBnb3RvIEVycm9yOwogICAgfQoKICAgIGlmIChUcmFuc2ZlckZ1bmN0aW9uKSB7CgogICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnR3JheVRSQ1RhZywgKHZvaWQqKSBUcmFuc2ZlckZ1bmN0aW9uKSkgZ290byBFcnJvcjsKICAgIH0KCiAgICByZXR1cm4gaElDQzsKCkVycm9yOgogICAgaWYgKGhJQ0MpCiAgICAgICAgY21zQ2xvc2VQcm9maWxlKGhJQ0MpOwogICAgcmV0dXJuIE5VTEw7Cn0KCgoKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZUdyYXlQcm9maWxlKGNvbnN0IGNtc0NJRXh5WSogV2hpdGVQb2ludCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNtc1RvbmVDdXJ2ZSogVHJhbnNmZXJGdW5jdGlvbikKewogICAgcmV0dXJuIGNtc0NyZWF0ZUdyYXlQcm9maWxlVEhSKE5VTEwsIFdoaXRlUG9pbnQsIFRyYW5zZmVyRnVuY3Rpb24pOwp9CgovLyBUaGlzIGlzIGEgZGV2aWNlbGluayBvcGVyYXRpbmcgaW4gdGhlIHRhcmdldCBjb2xvcnNwYWNlIHdpdGggYXMgbWFueSB0cmFuc2ZlciBmdW5jdGlvbnMgYXMgY29tcG9uZW50cwoKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZUxpbmVhcml6YXRpb25EZXZpY2VMaW5rVEhSKGNtc0NvbnRleHQgQ29udGV4dElELAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zQ29sb3JTcGFjZVNpZ25hdHVyZSBDb2xvclNwYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zVG9uZUN1cnZlKiBjb25zdCBUcmFuc2ZlckZ1bmN0aW9uc1tdKQp7CiAgICBjbXNIUFJPRklMRSBoSUNDOwogICAgY21zUGlwZWxpbmUqIFBpcGVsaW5lOwogICAgaW50IG5DaGFubmVsczsKCiAgICBoSUNDID0gY21zQ3JlYXRlUHJvZmlsZVBsYWNlaG9sZGVyKENvbnRleHRJRCk7CiAgICBpZiAoIWhJQ0MpCiAgICAgICAgcmV0dXJuIE5VTEw7CgogICAgY21zU2V0UHJvZmlsZVZlcnNpb24oaElDQywgNC4zKTsKCiAgICBjbXNTZXREZXZpY2VDbGFzcyhoSUNDLCAgICAgIGNtc1NpZ0xpbmtDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhJQ0MsICAgICAgIENvbG9yU3BhY2UpOwogICAgY21zU2V0UENTKGhJQ0MsICAgICAgICAgICAgICBDb2xvclNwYWNlKTsKCiAgICBjbXNTZXRIZWFkZXJSZW5kZXJpbmdJbnRlbnQoaElDQywgIElOVEVOVF9QRVJDRVBUVUFMKTsKCiAgICAvLyBTZXQgdXAgY2hhbm5lbHMKICAgIG5DaGFubmVscyA9IGNtc0NoYW5uZWxzT2YoQ29sb3JTcGFjZSk7CgogICAgLy8gQ3JlYXRlcyBhIFBpcGVsaW5lIHdpdGggcHJlbGluZWFyaXphdGlvbiBzdGVwIG9ubHkKICAgIFBpcGVsaW5lID0gY21zUGlwZWxpbmVBbGxvYyhDb250ZXh0SUQsIG5DaGFubmVscywgbkNoYW5uZWxzKTsKICAgIGlmIChQaXBlbGluZSA9PSBOVUxMKSBnb3RvIEVycm9yOwoKCiAgICAvLyBDb3B5IHRhYmxlcyB0byBQaXBlbGluZQogICAgaWYgKCFjbXNQaXBlbGluZUluc2VydFN0YWdlKFBpcGVsaW5lLCBjbXNBVF9CRUdJTiwgY21zU3RhZ2VBbGxvY1RvbmVDdXJ2ZXMoQ29udGV4dElELCBuQ2hhbm5lbHMsIFRyYW5zZmVyRnVuY3Rpb25zKSkpCiAgICAgICAgZ290byBFcnJvcjsKCiAgICAvLyBDcmVhdGUgdGFncwogICAgaWYgKCFTZXRUZXh0VGFncyhoSUNDLCBMIkxpbmVhcml6YXRpb24gYnVpbHQtaW4iKSkgZ290byBFcnJvcjsKICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnQVRvQjBUYWcsICh2b2lkKikgUGlwZWxpbmUpKSBnb3RvIEVycm9yOwogICAgaWYgKCFTZXRTZXFEZXNjVGFnKGhJQ0MsICJMaW5lYXJpemF0aW9uIGJ1aWx0LWluIikpIGdvdG8gRXJyb3I7CgogICAgLy8gUGlwZWxpbmUgaXMgYWxyZWFkeSBvbiB2aXJ0dWFsIHByb2ZpbGUKICAgIGNtc1BpcGVsaW5lRnJlZShQaXBlbGluZSk7CgogICAgLy8gT2ssIGRvbmUKICAgIHJldHVybiBoSUNDOwoKRXJyb3I6CiAgICBjbXNQaXBlbGluZUZyZWUoUGlwZWxpbmUpOwogICAgaWYgKGhJQ0MpCiAgICAgICAgY21zQ2xvc2VQcm9maWxlKGhJQ0MpOwoKCiAgICByZXR1cm4gTlVMTDsKfQoKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZUxpbmVhcml6YXRpb25EZXZpY2VMaW5rKGNtc0NvbG9yU3BhY2VTaWduYXR1cmUgQ29sb3JTcGFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbXNUb25lQ3VydmUqIGNvbnN0IFRyYW5zZmVyRnVuY3Rpb25zW10pCnsKICAgIHJldHVybiBjbXNDcmVhdGVMaW5lYXJpemF0aW9uRGV2aWNlTGlua1RIUihOVUxMLCBDb2xvclNwYWNlLCBUcmFuc2ZlckZ1bmN0aW9ucyk7Cn0KCi8vIEluay1saW1pdGluZyBhbGdvcml0aG0KLy8KLy8gIFN1bSA9IEMgKyBNICsgWSArIEsKLy8gIElmIFN1bSA+IElua0xpbWl0Ci8vICAgICAgICBSYXRpbz0gMSAtIChTdW0gLSBJbmtMaW1pdCkgLyAoQyArIE0gKyBZKQovLyAgICAgICAgaWYgUmF0aW8gPDAKLy8gICAgICAgICAgICAgIFJhdGlvPTAKLy8gICAgICAgIGVuZGlmCi8vICAgICBFbHNlCi8vICAgICAgICAgUmF0aW89MQovLyAgICAgZW5kaWYKLy8KLy8gICAgIEMgPSBSYXRpbyAqIEMKLy8gICAgIE0gPSBSYXRpbyAqIE0KLy8gICAgIFkgPSBSYXRpbyAqIFkKLy8gICAgIEs6IERvZXMgbm90IGNoYW5nZQoKc3RhdGljCmludCBJbmtMaW1pdGluZ1NhbXBsZXIocmVnaXN0ZXIgY29uc3QgY21zVUludDE2TnVtYmVyIEluW10sIHJlZ2lzdGVyIGNtc1VJbnQxNk51bWJlciBPdXRbXSwgcmVnaXN0ZXIgdm9pZCogQ2FyZ28pCnsKICAgIGNtc0Zsb2F0NjROdW1iZXIgSW5rTGltaXQgPSAqKGNtc0Zsb2F0NjROdW1iZXIgKikgQ2FyZ287CiAgICBjbXNGbG9hdDY0TnVtYmVyIFN1bUNNWSwgU3VtQ01ZSywgUmF0aW87CgogICAgSW5rTGltaXQgPSAoSW5rTGltaXQgKiA2NTUuMzUpOwoKICAgIFN1bUNNWSAgID0gSW5bMF0gICsgSW5bMV0gKyBJblsyXTsKICAgIFN1bUNNWUsgID0gU3VtQ01ZICsgSW5bM107CgogICAgaWYgKFN1bUNNWUsgPiBJbmtMaW1pdCkgewoKICAgICAgICBSYXRpbyA9IDEgLSAoKFN1bUNNWUsgLSBJbmtMaW1pdCkgLyBTdW1DTVkpOwogICAgICAgIGlmIChSYXRpbyA8IDApCiAgICAgICAgICAgIFJhdGlvID0gMDsKICAgIH0KICAgIGVsc2UgUmF0aW8gPSAxOwoKICAgIE91dFswXSA9IF9jbXNRdWlja1NhdHVyYXRlV29yZChJblswXSAqIFJhdGlvKTsgICAgIC8vIEMKICAgIE91dFsxXSA9IF9jbXNRdWlja1NhdHVyYXRlV29yZChJblsxXSAqIFJhdGlvKTsgICAgIC8vIE0KICAgIE91dFsyXSA9IF9jbXNRdWlja1NhdHVyYXRlV29yZChJblsyXSAqIFJhdGlvKTsgICAgIC8vIFkKCiAgICBPdXRbM10gPSBJblszXTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLICh1bnRvdWNoZWQpCgogICAgcmV0dXJuIFRSVUU7Cn0KCi8vIFRoaXMgaXMgYSBkZXZpY2VsaW5rIG9wZXJhdGluZyBpbiBDTVlLIGZvciBpbmstbGltaXRpbmcKCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVJbmtMaW1pdGluZ0RldmljZUxpbmtUSFIoY21zQ29udGV4dCBDb250ZXh0SUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zQ29sb3JTcGFjZVNpZ25hdHVyZSBDb2xvclNwYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc0Zsb2F0NjROdW1iZXIgTGltaXQpCnsKICAgIGNtc0hQUk9GSUxFIGhJQ0M7CiAgICBjbXNQaXBlbGluZSogTFVUOwogICAgY21zU3RhZ2UqIENMVVQ7CiAgICBpbnQgbkNoYW5uZWxzOwoKICAgIGlmIChDb2xvclNwYWNlICE9IGNtc1NpZ0NteWtEYXRhKSB7CiAgICAgICAgY21zU2lnbmFsRXJyb3IoQ29udGV4dElELCBjbXNFUlJPUl9DT0xPUlNQQUNFX0NIRUNLLCAiSW5rTGltaXRpbmc6IE9ubHkgQ01ZSyBjdXJyZW50bHkgc3VwcG9ydGVkIik7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CgogICAgaWYgKExpbWl0IDwgMC4wIHx8IExpbWl0ID4gNDAwKSB7CgogICAgICAgIGNtc1NpZ25hbEVycm9yKENvbnRleHRJRCwgY21zRVJST1JfUkFOR0UsICJJbmtMaW1pdGluZzogTGltaXQgc2hvdWxkIGJlIGJldHdlZW4gMC4uNDAwIik7CiAgICAgICAgaWYgKExpbWl0IDwgMCkgTGltaXQgPSAwOwogICAgICAgIGlmIChMaW1pdCA+IDQwMCkgTGltaXQgPSA0MDA7CgogICAgfQoKICAgIGhJQ0MgPSBjbXNDcmVhdGVQcm9maWxlUGxhY2Vob2xkZXIoQ29udGV4dElEKTsKICAgIGlmICghaElDQykgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbid0IGFsbG9jYXRlCiAgICAgICAgcmV0dXJuIE5VTEw7CgogICAgY21zU2V0UHJvZmlsZVZlcnNpb24oaElDQywgNC4zKTsKCiAgICBjbXNTZXREZXZpY2VDbGFzcyhoSUNDLCAgICAgIGNtc1NpZ0xpbmtDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhJQ0MsICAgICAgIENvbG9yU3BhY2UpOwogICAgY21zU2V0UENTKGhJQ0MsICAgICAgICAgICAgICBDb2xvclNwYWNlKTsKCiAgICBjbXNTZXRIZWFkZXJSZW5kZXJpbmdJbnRlbnQoaElDQywgIElOVEVOVF9QRVJDRVBUVUFMKTsKCgogICAgLy8gQ3JlYXRlcyBhIFBpcGVsaW5lIHdpdGggM0QgZ3JpZCBvbmx5CiAgICBMVVQgPSBjbXNQaXBlbGluZUFsbG9jKENvbnRleHRJRCwgNCwgNCk7CiAgICBpZiAoTFVUID09IE5VTEwpIGdvdG8gRXJyb3I7CgoKICAgIG5DaGFubmVscyA9IGNtc0NoYW5uZWxzT2YoQ29sb3JTcGFjZSk7CgogICAgQ0xVVCA9IGNtc1N0YWdlQWxsb2NDTHV0MTZiaXQoQ29udGV4dElELCAxNywgbkNoYW5uZWxzLCBuQ2hhbm5lbHMsIE5VTEwpOwogICAgaWYgKENMVVQgPT0gTlVMTCkgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1N0YWdlU2FtcGxlQ0x1dDE2Yml0KENMVVQsIElua0xpbWl0aW5nU2FtcGxlciwgKHZvaWQqKSAmTGltaXQsIDApKSBnb3RvIEVycm9yOwoKICAgIGlmICghY21zUGlwZWxpbmVJbnNlcnRTdGFnZShMVVQsIGNtc0FUX0JFR0lOLCBfY21zU3RhZ2VBbGxvY0lkZW50aXR5Q3VydmVzKENvbnRleHRJRCwgbkNoYW5uZWxzKSkgfHwKICAgICAgICAhY21zUGlwZWxpbmVJbnNlcnRTdGFnZShMVVQsIGNtc0FUX0VORCwgQ0xVVCkgfHwKICAgICAgICAhY21zUGlwZWxpbmVJbnNlcnRTdGFnZShMVVQsIGNtc0FUX0VORCwgX2Ntc1N0YWdlQWxsb2NJZGVudGl0eUN1cnZlcyhDb250ZXh0SUQsIG5DaGFubmVscykpKQogICAgICAgIGdvdG8gRXJyb3I7CgogICAgLy8gQ3JlYXRlIHRhZ3MKICAgIGlmICghU2V0VGV4dFRhZ3MoaElDQywgTCJpbmstbGltaXRpbmcgYnVpbHQtaW4iKSkgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0FUb0IwVGFnLCAodm9pZCopIExVVCkpICBnb3RvIEVycm9yOwogICAgaWYgKCFTZXRTZXFEZXNjVGFnKGhJQ0MsICJpbmstbGltaXRpbmcgYnVpbHQtaW4iKSkgZ290byBFcnJvcjsKCiAgICAvLyBjbXNQaXBlbGluZSBpcyBhbHJlYWR5IG9uIHZpcnR1YWwgcHJvZmlsZQogICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CgogICAgLy8gT2ssIGRvbmUKICAgIHJldHVybiBoSUNDOwoKRXJyb3I6CiAgICBpZiAoTFVUICE9IE5VTEwpCiAgICAgICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CgogICAgaWYgKGhJQ0MgIT0gTlVMTCkKICAgICAgICBjbXNDbG9zZVByb2ZpbGUoaElDQyk7CgogICAgcmV0dXJuIE5VTEw7Cn0KCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVJbmtMaW1pdGluZ0RldmljZUxpbmsoY21zQ29sb3JTcGFjZVNpZ25hdHVyZSBDb2xvclNwYWNlLCBjbXNGbG9hdDY0TnVtYmVyIExpbWl0KQp7CiAgICByZXR1cm4gY21zQ3JlYXRlSW5rTGltaXRpbmdEZXZpY2VMaW5rVEhSKE5VTEwsIENvbG9yU3BhY2UsIExpbWl0KTsKfQoKCi8vIENyZWF0ZXMgYSBmYWtlIExhYiBpZGVudGl0eS4KY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZUxhYjJQcm9maWxlVEhSKGNtc0NvbnRleHQgQ29udGV4dElELCBjb25zdCBjbXNDSUV4eVkqIFdoaXRlUG9pbnQpCnsKICAgIGNtc0hQUk9GSUxFIGhQcm9maWxlOwogICAgY21zUGlwZWxpbmUqIExVVCA9IE5VTEw7CgogICAgaFByb2ZpbGUgPSBjbXNDcmVhdGVSR0JQcm9maWxlVEhSKENvbnRleHRJRCwgV2hpdGVQb2ludCA9PSBOVUxMID8gY21zRDUwX3h5WSgpIDogV2hpdGVQb2ludCwgTlVMTCwgTlVMTCk7CiAgICBpZiAoaFByb2ZpbGUgPT0gTlVMTCkgcmV0dXJuIE5VTEw7CgogICAgY21zU2V0UHJvZmlsZVZlcnNpb24oaFByb2ZpbGUsIDIuMSk7CgogICAgY21zU2V0RGV2aWNlQ2xhc3MoaFByb2ZpbGUsIGNtc1NpZ0Fic3RyYWN0Q2xhc3MpOwogICAgY21zU2V0Q29sb3JTcGFjZShoUHJvZmlsZSwgIGNtc1NpZ0xhYkRhdGEpOwogICAgY21zU2V0UENTKGhQcm9maWxlLCAgICAgICAgIGNtc1NpZ0xhYkRhdGEpOwoKICAgIGlmICghU2V0VGV4dFRhZ3MoaFByb2ZpbGUsIEwiTGFiIGlkZW50aXR5IGJ1aWx0LWluIikpIHJldHVybiBOVUxMOwoKICAgIC8vIEFuIGlkZW50aXR5IExVVCBpcyBhbGwgd2UgbmVlZAogICAgTFVUID0gY21zUGlwZWxpbmVBbGxvYyhDb250ZXh0SUQsIDMsIDMpOwogICAgaWYgKExVVCA9PSBOVUxMKSBnb3RvIEVycm9yOwoKICAgIGlmICghY21zUGlwZWxpbmVJbnNlcnRTdGFnZShMVVQsIGNtc0FUX0JFR0lOLCBfY21zU3RhZ2VBbGxvY0lkZW50aXR5Q0x1dChDb250ZXh0SUQsIDMpKSkKICAgICAgICBnb3RvIEVycm9yOwoKICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIGNtc1NpZ0FUb0IwVGFnLCBMVVQpKSBnb3RvIEVycm9yOwogICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CgogICAgcmV0dXJuIGhQcm9maWxlOwoKRXJyb3I6CgogICAgaWYgKExVVCAhPSBOVUxMKQogICAgICAgIGNtc1BpcGVsaW5lRnJlZShMVVQpOwoKICAgIGlmIChoUHJvZmlsZSAhPSBOVUxMKQogICAgICAgIGNtc0Nsb3NlUHJvZmlsZShoUHJvZmlsZSk7CgogICAgcmV0dXJuIE5VTEw7Cn0KCgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlTGFiMlByb2ZpbGUoY29uc3QgY21zQ0lFeHlZKiBXaGl0ZVBvaW50KQp7CiAgICByZXR1cm4gY21zQ3JlYXRlTGFiMlByb2ZpbGVUSFIoTlVMTCwgV2hpdGVQb2ludCk7Cn0KCgovLyBDcmVhdGVzIGEgZmFrZSBMYWIgVjQgaWRlbnRpdHkuCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVMYWI0UHJvZmlsZVRIUihjbXNDb250ZXh0IENvbnRleHRJRCwgY29uc3QgY21zQ0lFeHlZKiBXaGl0ZVBvaW50KQp7CiAgICBjbXNIUFJPRklMRSBoUHJvZmlsZTsKICAgIGNtc1BpcGVsaW5lKiBMVVQgPSBOVUxMOwoKICAgIGhQcm9maWxlID0gY21zQ3JlYXRlUkdCUHJvZmlsZVRIUihDb250ZXh0SUQsIFdoaXRlUG9pbnQgPT0gTlVMTCA/IGNtc0Q1MF94eVkoKSA6IFdoaXRlUG9pbnQsIE5VTEwsIE5VTEwpOwogICAgaWYgKGhQcm9maWxlID09IE5VTEwpIHJldHVybiBOVUxMOwoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhQcm9maWxlLCA0LjMpOwoKICAgIGNtc1NldERldmljZUNsYXNzKGhQcm9maWxlLCBjbXNTaWdBYnN0cmFjdENsYXNzKTsKICAgIGNtc1NldENvbG9yU3BhY2UoaFByb2ZpbGUsICBjbXNTaWdMYWJEYXRhKTsKICAgIGNtc1NldFBDUyhoUHJvZmlsZSwgICAgICAgICBjbXNTaWdMYWJEYXRhKTsKCiAgICBpZiAoIVNldFRleHRUYWdzKGhQcm9maWxlLCBMIkxhYiBpZGVudGl0eSBidWlsdC1pbiIpKSBnb3RvIEVycm9yOwoKICAgIC8vIEFuIGVtcHR5IExVVHMgaXMgYWxsIHdlIG5lZWQKICAgIExVVCA9IGNtc1BpcGVsaW5lQWxsb2MoQ29udGV4dElELCAzLCAzKTsKICAgIGlmIChMVVQgPT0gTlVMTCkgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9CRUdJTiwgX2Ntc1N0YWdlQWxsb2NJZGVudGl0eUN1cnZlcyhDb250ZXh0SUQsIDMpKSkKICAgICAgICBnb3RvIEVycm9yOwoKICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIGNtc1NpZ0FUb0IwVGFnLCBMVVQpKSBnb3RvIEVycm9yOwogICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CgogICAgcmV0dXJuIGhQcm9maWxlOwoKRXJyb3I6CgogICAgaWYgKExVVCAhPSBOVUxMKQogICAgICAgIGNtc1BpcGVsaW5lRnJlZShMVVQpOwoKICAgIGlmIChoUHJvZmlsZSAhPSBOVUxMKQogICAgICAgIGNtc0Nsb3NlUHJvZmlsZShoUHJvZmlsZSk7CgogICAgcmV0dXJuIE5VTEw7Cn0KCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVMYWI0UHJvZmlsZShjb25zdCBjbXNDSUV4eVkqIFdoaXRlUG9pbnQpCnsKICAgIHJldHVybiBjbXNDcmVhdGVMYWI0UHJvZmlsZVRIUihOVUxMLCBXaGl0ZVBvaW50KTsKfQoKCi8vIENyZWF0ZXMgYSBmYWtlIFhZWiBpZGVudGl0eQpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlWFlaUHJvZmlsZVRIUihjbXNDb250ZXh0IENvbnRleHRJRCkKewogICAgY21zSFBST0ZJTEUgaFByb2ZpbGU7CiAgICBjbXNQaXBlbGluZSogTFVUID0gTlVMTDsKCiAgICBoUHJvZmlsZSA9IGNtc0NyZWF0ZVJHQlByb2ZpbGVUSFIoQ29udGV4dElELCBjbXNENTBfeHlZKCksIE5VTEwsIE5VTEwpOwogICAgaWYgKGhQcm9maWxlID09IE5VTEwpIHJldHVybiBOVUxMOwoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhQcm9maWxlLCA0LjMpOwoKICAgIGNtc1NldERldmljZUNsYXNzKGhQcm9maWxlLCBjbXNTaWdBYnN0cmFjdENsYXNzKTsKICAgIGNtc1NldENvbG9yU3BhY2UoaFByb2ZpbGUsICBjbXNTaWdYWVpEYXRhKTsKICAgIGNtc1NldFBDUyhoUHJvZmlsZSwgICAgICAgICBjbXNTaWdYWVpEYXRhKTsKCiAgICBpZiAoIVNldFRleHRUYWdzKGhQcm9maWxlLCBMIlhZWiBpZGVudGl0eSBidWlsdC1pbiIpKSBnb3RvIEVycm9yOwoKICAgIC8vIEFuIGlkZW50aXR5IExVVCBpcyBhbGwgd2UgbmVlZAogICAgTFVUID0gY21zUGlwZWxpbmVBbGxvYyhDb250ZXh0SUQsIDMsIDMpOwogICAgaWYgKExVVCA9PSBOVUxMKSBnb3RvIEVycm9yOwoKICAgIGlmICghY21zUGlwZWxpbmVJbnNlcnRTdGFnZShMVVQsIGNtc0FUX0JFR0lOLCBfY21zU3RhZ2VBbGxvY0lkZW50aXR5Q3VydmVzKENvbnRleHRJRCwgMykpKQogICAgICAgIGdvdG8gRXJyb3I7CgogICAgaWYgKCFjbXNXcml0ZVRhZyhoUHJvZmlsZSwgY21zU2lnQVRvQjBUYWcsIExVVCkpIGdvdG8gRXJyb3I7CiAgICBjbXNQaXBlbGluZUZyZWUoTFVUKTsKCiAgICByZXR1cm4gaFByb2ZpbGU7CgpFcnJvcjoKCiAgICBpZiAoTFVUICE9IE5VTEwpCiAgICAgICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CgogICAgaWYgKGhQcm9maWxlICE9IE5VTEwpCiAgICAgICAgY21zQ2xvc2VQcm9maWxlKGhQcm9maWxlKTsKCiAgICByZXR1cm4gTlVMTDsKfQoKCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVYWVpQcm9maWxlKHZvaWQpCnsKICAgIHJldHVybiBjbXNDcmVhdGVYWVpQcm9maWxlVEhSKE5VTEwpOwp9CgoKLy9zUkdCIEN1cnZlcyBhcmUgZGVmaW5lZCBieToKLy8KLy9JZiAgUpJzUkdCLEeSc1JHQiwgQpJzUkdCIDwgMC4wNDA0NQovLwovLyAgICBSID0gIFKSc1JHQiAvIDEyLjkyCi8vICAgIEcgPSAgR5JzUkdCIC8gMTIuOTIKLy8gICAgQiA9ICBCknNSR0IgLyAxMi45MgovLwovLwovL2Vsc2UgaWYgIFKSc1JHQixHknNSR0IsIEKSc1JHQiA+PSAwLjA0MDQ1Ci8vCi8vICAgIFIgPSAoKFKSc1JHQiArIDAuMDU1KSAvIDEuMDU1KV4yLjQKLy8gICAgRyA9ICgoR5JzUkdCICsgMC4wNTUpIC8gMS4wNTUpXjIuNAovLyAgICBCID0gKChCknNSR0IgKyAwLjA1NSkgLyAxLjA1NSleMi40CgpzdGF0aWMKY21zVG9uZUN1cnZlKiBCdWlsZF9zUkdCR2FtbWEoY21zQ29udGV4dCBDb250ZXh0SUQpCnsKICAgIGNtc0Zsb2F0NjROdW1iZXIgUGFyYW1ldGVyc1s1XTsKCiAgICBQYXJhbWV0ZXJzWzBdID0gMi40OwogICAgUGFyYW1ldGVyc1sxXSA9IDEuIC8gMS4wNTU7CiAgICBQYXJhbWV0ZXJzWzJdID0gMC4wNTUgLyAxLjA1NTsKICAgIFBhcmFtZXRlcnNbM10gPSAxLiAvIDEyLjkyOwogICAgUGFyYW1ldGVyc1s0XSA9IDAuMDQwNDU7CgogICAgcmV0dXJuIGNtc0J1aWxkUGFyYW1ldHJpY1RvbmVDdXJ2ZShDb250ZXh0SUQsIDQsIFBhcmFtZXRlcnMpOwp9CgovLyBDcmVhdGUgdGhlIElDQyB2aXJ0dWFsIHByb2ZpbGUgZm9yIHNSR0Igc3BhY2UKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZV9zUkdCUHJvZmlsZVRIUihjbXNDb250ZXh0IENvbnRleHRJRCkKewogICAgICAgY21zQ0lFeHlZICAgICAgIEQ2NSA9IHsgMC4zMTI3LCAwLjMyOTAsIDEuMCB9OwogICAgICAgY21zQ0lFeHlZVFJJUExFIFJlYzcwOVByaW1hcmllcyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7MC42NDAwLCAwLjMzMDAsIDEuMH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgezAuMzAwMCwgMC42MDAwLCAxLjB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHswLjE1MDAsIDAuMDYwMCwgMS4wfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICBjbXNUb25lQ3VydmUqIEdhbW1hMjJbM107CiAgICAgICBjbXNIUFJPRklMRSAgaHNSR0I7CgogICAgICAvLyBjbXNXaGl0ZVBvaW50RnJvbVRlbXAoJkQ2NSwgNjUwNCk7CiAgICAgICBHYW1tYTIyWzBdID0gR2FtbWEyMlsxXSA9IEdhbW1hMjJbMl0gPSBCdWlsZF9zUkdCR2FtbWEoQ29udGV4dElEKTsKICAgICAgIGlmIChHYW1tYTIyWzBdID09IE5VTEwpIHJldHVybiBOVUxMOwoKICAgICAgIGhzUkdCID0gY21zQ3JlYXRlUkdCUHJvZmlsZVRIUihDb250ZXh0SUQsICZENjUsICZSZWM3MDlQcmltYXJpZXMsIEdhbW1hMjIpOwogICAgICAgY21zRnJlZVRvbmVDdXJ2ZShHYW1tYTIyWzBdKTsKICAgICAgIGlmIChoc1JHQiA9PSBOVUxMKSByZXR1cm4gTlVMTDsKCiAgICAgICBpZiAoIVNldFRleHRUYWdzKGhzUkdCLCBMInNSR0IgYnVpbHQtaW4iKSkgewogICAgICAgICAgIGNtc0Nsb3NlUHJvZmlsZShoc1JHQik7CiAgICAgICAgICAgcmV0dXJuIE5VTEw7CiAgICAgICB9CgogICAgICAgcmV0dXJuIGhzUkdCOwp9CgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlX3NSR0JQcm9maWxlKHZvaWQpCnsKICAgIHJldHVybiBjbXNDcmVhdGVfc1JHQlByb2ZpbGVUSFIoTlVMTCk7Cn0KCgoKdHlwZWRlZiBzdHJ1Y3QgewogICAgICAgICAgICAgICAgY21zRmxvYXQ2NE51bWJlciBCcmlnaHRuZXNzOwogICAgICAgICAgICAgICAgY21zRmxvYXQ2NE51bWJlciBDb250cmFzdDsKICAgICAgICAgICAgICAgIGNtc0Zsb2F0NjROdW1iZXIgSHVlOwogICAgICAgICAgICAgICAgY21zRmxvYXQ2NE51bWJlciBTYXR1cmF0aW9uOwogICAgICAgICAgICAgICAgY21zQm9vbCAgICAgICAgICBsQWRqdXN0V1A7CiAgICAgICAgICAgICAgICBjbXNDSUVYWVogV1BzcmMsIFdQZGVzdDsKCn0gQkNIU1dBREpVU1RTLCAqTFBCQ0hTV0FESlVTVFM7CgoKc3RhdGljCmludCBiY2hzd1NhbXBsZXIocmVnaXN0ZXIgY29uc3QgY21zVUludDE2TnVtYmVyIEluW10sIHJlZ2lzdGVyIGNtc1VJbnQxNk51bWJlciBPdXRbXSwgcmVnaXN0ZXIgdm9pZCogQ2FyZ28pCnsKICAgIGNtc0NJRUxhYiBMYWJJbiwgTGFiT3V0OwogICAgY21zQ0lFTENoIExDaEluLCBMQ2hPdXQ7CiAgICBjbXNDSUVYWVogWFlaOwogICAgTFBCQ0hTV0FESlVTVFMgYmNoc3cgPSAoTFBCQ0hTV0FESlVTVFMpIENhcmdvOwoKCiAgICBjbXNMYWJFbmNvZGVkMkZsb2F0KCZMYWJJbiwgSW4pOwoKCiAgICBjbXNMYWIyTENoKCZMQ2hJbiwgJkxhYkluKTsKCiAgICAvLyBEbyBzb21lIGFkanVzdHMgb24gTENoCgogICAgTENoT3V0LkwgPSBMQ2hJbi5MICogYmNoc3cgLT5Db250cmFzdCArIGJjaHN3IC0+QnJpZ2h0bmVzczsKICAgIExDaE91dC5DID0gTENoSW4uQyArIGJjaHN3IC0+IFNhdHVyYXRpb247CiAgICBMQ2hPdXQuaCA9IExDaEluLmggKyBiY2hzdyAtPiBIdWU7CgoKICAgIGNtc0xDaDJMYWIoJkxhYk91dCwgJkxDaE91dCk7CgogICAgLy8gTW92ZSB3aGl0ZSBwb2ludCBpbiBMYWIKICAgIGlmIChiY2hzdy0+bEFkanVzdFdQKSB7CiAgICAgICAgICAgY21zTGFiMlhZWigmYmNoc3ctPldQc3JjLCAmWFlaLCAmTGFiT3V0KTsKICAgICAgICAgICBjbXNYWVoyTGFiKCZiY2hzdy0+V1BkZXN0LCAmTGFiT3V0LCAmWFlaKTsKICAgIH0KCiAgICAvLyBCYWNrIHRvIGVuY29kZWQKCiAgICBjbXNGbG9hdDJMYWJFbmNvZGVkKE91dCwgJkxhYk91dCk7CgogICAgcmV0dXJuIFRSVUU7Cn0KCgovLyBDcmVhdGVzIGFuIGFic3RyYWN0IHByb2ZpbGUgb3BlcmF0aW5nIGluIExhYiBzcGFjZSBmb3IgQnJpZ2h0bmVzcywKLy8gY29udHJhc3QsIFNhdHVyYXRpb24gYW5kIHdoaXRlIHBvaW50IGRpc3BsYWNlbWVudAoKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZUJDSFNXYWJzdHJhY3RQcm9maWxlVEhSKGNtc0NvbnRleHQgQ29udGV4dElELAogICAgaW50IG5MVVRQb2ludHMsCiAgICBjbXNGbG9hdDY0TnVtYmVyIEJyaWdodCwKICAgIGNtc0Zsb2F0NjROdW1iZXIgQ29udHJhc3QsCiAgICBjbXNGbG9hdDY0TnVtYmVyIEh1ZSwKICAgIGNtc0Zsb2F0NjROdW1iZXIgU2F0dXJhdGlvbiwKICAgIGludCBUZW1wU3JjLAogICAgaW50IFRlbXBEZXN0KQp7CiAgICBjbXNIUFJPRklMRSBoSUNDOwogICAgY21zUGlwZWxpbmUqIFBpcGVsaW5lOwogICAgQkNIU1dBREpVU1RTIGJjaHN3OwogICAgY21zQ0lFeHlZIFdoaXRlUG50OwogICAgY21zU3RhZ2UqIENMVVQ7CiAgICBjbXNVSW50MzJOdW1iZXIgRGltZW5zaW9uc1tNQVhfSU5QVVRfRElNRU5TSU9OU107CiAgICBpbnQgaTsKCiAgICBiY2hzdy5CcmlnaHRuZXNzID0gQnJpZ2h0OwogICAgYmNoc3cuQ29udHJhc3QgICA9IENvbnRyYXN0OwogICAgYmNoc3cuSHVlICAgICAgICA9IEh1ZTsKICAgIGJjaHN3LlNhdHVyYXRpb24gPSBTYXR1cmF0aW9uOwogICAgaWYgKFRlbXBTcmMgPT0gVGVtcERlc3QpIHsKCiAgICAgICAgICAgYmNoc3cubEFkanVzdFdQID0gRkFMU0U7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICAgICBiY2hzdy5sQWRqdXN0V1AgPSBUUlVFOwogICAgICAgICAgIGNtc1doaXRlUG9pbnRGcm9tVGVtcCgmV2hpdGVQbnQsIFRlbXBTcmMpOwogICAgICAgICAgIGNtc3h5WTJYWVooJmJjaHN3LldQc3JjLCAmV2hpdGVQbnQpOwogICAgICAgICAgIGNtc1doaXRlUG9pbnRGcm9tVGVtcCgmV2hpdGVQbnQsIFRlbXBEZXN0KTsKICAgICAgICAgICBjbXN4eVkyWFlaKCZiY2hzdy5XUGRlc3QsICZXaGl0ZVBudCk7CgogICAgfQoKICAgIGhJQ0MgPSBjbXNDcmVhdGVQcm9maWxlUGxhY2Vob2xkZXIoQ29udGV4dElEKTsKICAgIGlmICghaElDQykgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbid0IGFsbG9jYXRlCiAgICAgICAgcmV0dXJuIE5VTEw7CgogICAgY21zU2V0RGV2aWNlQ2xhc3MoaElDQywgICAgICBjbXNTaWdBYnN0cmFjdENsYXNzKTsKICAgIGNtc1NldENvbG9yU3BhY2UoaElDQywgICAgICAgY21zU2lnTGFiRGF0YSk7CiAgICBjbXNTZXRQQ1MoaElDQywgICAgICAgICAgICAgIGNtc1NpZ0xhYkRhdGEpOwoKICAgIGNtc1NldEhlYWRlclJlbmRlcmluZ0ludGVudChoSUNDLCAgSU5URU5UX1BFUkNFUFRVQUwpOwoKICAgIC8vIENyZWF0ZXMgYSBQaXBlbGluZSB3aXRoIDNEIGdyaWQgb25seQogICAgUGlwZWxpbmUgPSBjbXNQaXBlbGluZUFsbG9jKENvbnRleHRJRCwgMywgMyk7CiAgICBpZiAoUGlwZWxpbmUgPT0gTlVMTCkgewogICAgICAgIGNtc0Nsb3NlUHJvZmlsZShoSUNDKTsKICAgICAgICByZXR1cm4gTlVMTDsKICAgIH0KCiAgICBmb3IgKGk9MDsgaSA8IE1BWF9JTlBVVF9ESU1FTlNJT05TOyBpKyspIERpbWVuc2lvbnNbaV0gPSBuTFVUUG9pbnRzOwogICAgQ0xVVCA9IGNtc1N0YWdlQWxsb2NDTHV0MTZiaXRHcmFudWxhcihDb250ZXh0SUQsIERpbWVuc2lvbnMsIDMsIDMsIE5VTEwpOwogICAgaWYgKENMVVQgPT0gTlVMTCkgcmV0dXJuIE5VTEw7CgoKICAgIGlmICghY21zU3RhZ2VTYW1wbGVDTHV0MTZiaXQoQ0xVVCwgYmNoc3dTYW1wbGVyLCAodm9pZCopICZiY2hzdywgMCkpIHsKCiAgICAgICAgLy8gU2hvdWxkbid0IHJlYWNoIGhlcmUKICAgICAgICBnb3RvIEVycm9yOwogICAgfQoKICAgIGlmICghY21zUGlwZWxpbmVJbnNlcnRTdGFnZShQaXBlbGluZSwgY21zQVRfRU5ELCBDTFVUKSkgewogICAgICAgIGdvdG8gRXJyb3I7CiAgICB9CgogICAgLy8gQ3JlYXRlIHRhZ3MKICAgIGlmICghU2V0VGV4dFRhZ3MoaElDQywgTCJCQ0hTIGJ1aWx0LWluIikpIHJldHVybiBOVUxMOwoKICAgIGNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ01lZGlhV2hpdGVQb2ludFRhZywgKHZvaWQqKSBjbXNENTBfWFlaKCkpOwoKICAgIGNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0FUb0IwVGFnLCAodm9pZCopIFBpcGVsaW5lKTsKCiAgICAvLyBQaXBlbGluZSBpcyBhbHJlYWR5IG9uIHZpcnR1YWwgcHJvZmlsZQogICAgY21zUGlwZWxpbmVGcmVlKFBpcGVsaW5lKTsKCiAgICAvLyBPaywgZG9uZQogICAgcmV0dXJuIGhJQ0M7CgpFcnJvcjoKICAgIGNtc1BpcGVsaW5lRnJlZShQaXBlbGluZSk7CiAgICBjbXNDbG9zZVByb2ZpbGUoaElDQyk7CiAgICByZXR1cm4gTlVMTDsKfQoKCkNNU0FQSSBjbXNIUFJPRklMRSAgIENNU0VYUE9SVCBjbXNDcmVhdGVCQ0hTV2Fic3RyYWN0UHJvZmlsZShpbnQgbkxVVFBvaW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc0Zsb2F0NjROdW1iZXIgQnJpZ2h0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zRmxvYXQ2NE51bWJlciBDb250cmFzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc0Zsb2F0NjROdW1iZXIgSHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zRmxvYXQ2NE51bWJlciBTYXR1cmF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IFRlbXBTcmMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgVGVtcERlc3QpCnsKICAgIHJldHVybiBjbXNDcmVhdGVCQ0hTV2Fic3RyYWN0UHJvZmlsZVRIUihOVUxMLCBuTFVUUG9pbnRzLCBCcmlnaHQsIENvbnRyYXN0LCBIdWUsIFNhdHVyYXRpb24sIFRlbXBTcmMsIFRlbXBEZXN0KTsKfQoKCi8vIENyZWF0ZXMgYSBmYWtlIE5VTEwgcHJvZmlsZS4gVGhpcyBwcm9maWxlIHJldHVybiAxIGNoYW5uZWwgYXMgYWx3YXlzIDAuCi8vIElzIHVzZWZ1bCBvbmx5IGZvciBnYW11dCBjaGVja2luZyB0cmlja3MKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZU5VTExQcm9maWxlVEhSKGNtc0NvbnRleHQgQ29udGV4dElEKQp7CiAgICBjbXNIUFJPRklMRSBoUHJvZmlsZTsKICAgIGNtc1BpcGVsaW5lKiBMVVQgPSBOVUxMOwogICAgY21zU3RhZ2UqIFBvc3RMaW47CiAgICBjbXNUb25lQ3VydmUqIEVtcHR5VGFiOwogICAgY21zVUludDE2TnVtYmVyIFplcm9bMl0gPSB7IDAsIDAgfTsKCiAgICBoUHJvZmlsZSA9IGNtc0NyZWF0ZVByb2ZpbGVQbGFjZWhvbGRlcihDb250ZXh0SUQpOwogICAgaWYgKCFoUHJvZmlsZSkgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbid0IGFsbG9jYXRlCiAgICAgICAgcmV0dXJuIE5VTEw7CgogICAgY21zU2V0UHJvZmlsZVZlcnNpb24oaFByb2ZpbGUsIDQuMyk7CgogICAgaWYgKCFTZXRUZXh0VGFncyhoUHJvZmlsZSwgTCJOVUxMIHByb2ZpbGUgYnVpbHQtaW4iKSkgZ290byBFcnJvcjsKCgoKICAgIGNtc1NldERldmljZUNsYXNzKGhQcm9maWxlLCBjbXNTaWdPdXRwdXRDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhQcm9maWxlLCAgY21zU2lnR3JheURhdGEpOwogICAgY21zU2V0UENTKGhQcm9maWxlLCAgICAgICAgIGNtc1NpZ0xhYkRhdGEpOwoKICAgIC8vIEFuIGVtcHR5IExVVHMgaXMgYWxsIHdlIG5lZWQKICAgIExVVCA9IGNtc1BpcGVsaW5lQWxsb2MoQ29udGV4dElELCAxLCAxKTsKICAgIGlmIChMVVQgPT0gTlVMTCkgZ290byBFcnJvcjsKCiAgICBFbXB0eVRhYiA9IGNtc0J1aWxkVGFidWxhdGVkVG9uZUN1cnZlMTYoQ29udGV4dElELCAyLCBaZXJvKTsKICAgIFBvc3RMaW4gPSBjbXNTdGFnZUFsbG9jVG9uZUN1cnZlcyhDb250ZXh0SUQsIDEsICZFbXB0eVRhYik7CiAgICBjbXNGcmVlVG9uZUN1cnZlKEVtcHR5VGFiKTsKCiAgICBpZiAoIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9FTkQsIFBvc3RMaW4pKQogICAgICAgIGdvdG8gRXJyb3I7CgogICAgaWYgKCFjbXNXcml0ZVRhZyhoUHJvZmlsZSwgY21zU2lnQlRvQTBUYWcsICh2b2lkKikgTFVUKSkgZ290byBFcnJvcjsKICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIGNtc1NpZ01lZGlhV2hpdGVQb2ludFRhZywgY21zRDUwX1hZWigpKSkgZ290byBFcnJvcjsKCiAgICBjbXNQaXBlbGluZUZyZWUoTFVUKTsKICAgIHJldHVybiBoUHJvZmlsZTsKCkVycm9yOgoKICAgIGlmIChMVVQgIT0gTlVMTCkKICAgICAgICBjbXNQaXBlbGluZUZyZWUoTFVUKTsKCiAgICBpZiAoaFByb2ZpbGUgIT0gTlVMTCkKICAgICAgICBjbXNDbG9zZVByb2ZpbGUoaFByb2ZpbGUpOwoKICAgIHJldHVybiBOVUxMOwp9CgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlTlVMTFByb2ZpbGUodm9pZCkKewogICAgcmV0dXJuIGNtc0NyZWF0ZU5VTExQcm9maWxlVEhSKE5VTEwpOwp9CgoKc3RhdGljCmludCBJc1BDUyhjbXNDb2xvclNwYWNlU2lnbmF0dXJlIENvbG9yU3BhY2UpCnsKICAgIHJldHVybiAoQ29sb3JTcGFjZSA9PSBjbXNTaWdYWVpEYXRhIHx8CiAgICAgICAgICAgIENvbG9yU3BhY2UgPT0gY21zU2lnTGFiRGF0YSk7Cn0KCgpzdGF0aWMKdm9pZCBGaXhDb2xvclNwYWNlcyhjbXNIUFJPRklMRSBoUHJvZmlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zQ29sb3JTcGFjZVNpZ25hdHVyZSBDb2xvclNwYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbXNDb2xvclNwYWNlU2lnbmF0dXJlIFBDUywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zVUludDMyTnVtYmVyIGR3RmxhZ3MpCnsKICAgIGlmIChkd0ZsYWdzICYgY21zRkxBR1NfR1VFU1NERVZJQ0VDTEFTUykgewoKICAgICAgICAgICAgaWYgKElzUENTKENvbG9yU3BhY2UpICYmIElzUENTKFBDUykpIHsKCiAgICAgICAgICAgICAgICAgICAgY21zU2V0RGV2aWNlQ2xhc3MoaFByb2ZpbGUsICAgICAgY21zU2lnQWJzdHJhY3RDbGFzcyk7CiAgICAgICAgICAgICAgICAgICAgY21zU2V0Q29sb3JTcGFjZShoUHJvZmlsZSwgICAgICAgQ29sb3JTcGFjZSk7CiAgICAgICAgICAgICAgICAgICAgY21zU2V0UENTKGhQcm9maWxlLCAgICAgICAgICAgICAgUENTKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChJc1BDUyhDb2xvclNwYWNlKSAmJiAhSXNQQ1MoUENTKSkgewoKICAgICAgICAgICAgICAgICAgICBjbXNTZXREZXZpY2VDbGFzcyhoUHJvZmlsZSwgY21zU2lnT3V0cHV0Q2xhc3MpOwogICAgICAgICAgICAgICAgICAgIGNtc1NldFBDUyhoUHJvZmlsZSwgICAgICAgICBDb2xvclNwYWNlKTsKICAgICAgICAgICAgICAgICAgICBjbXNTZXRDb2xvclNwYWNlKGhQcm9maWxlLCAgUENTKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChJc1BDUyhQQ1MpICYmICFJc1BDUyhDb2xvclNwYWNlKSkgewoKICAgICAgICAgICAgICAgICAgIGNtc1NldERldmljZUNsYXNzKGhQcm9maWxlLCAgY21zU2lnSW5wdXRDbGFzcyk7CiAgICAgICAgICAgICAgICAgICBjbXNTZXRDb2xvclNwYWNlKGhQcm9maWxlLCAgIENvbG9yU3BhY2UpOwogICAgICAgICAgICAgICAgICAgY21zU2V0UENTKGhQcm9maWxlLCAgICAgICAgICBQQ1MpOwogICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICB9CgogICAgY21zU2V0RGV2aWNlQ2xhc3MoaFByb2ZpbGUsICAgICAgY21zU2lnTGlua0NsYXNzKTsKICAgIGNtc1NldENvbG9yU3BhY2UoaFByb2ZpbGUsICAgICAgIENvbG9yU3BhY2UpOwogICAgY21zU2V0UENTKGhQcm9maWxlLCAgICAgICAgICAgICAgUENTKTsKfQoKCgovLyBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgYSBuYW1lZCBjb2xvciBwcm9maWxlIGR1bXBpbmcgYWxsIHRoZSBjb250ZW50cyBvZiB0cmFuc2Zvcm0gdG8gYSBzaW5nbGUgcHJvZmlsZQovLyBJbiB0aGlzIHdheSwgTGl0dGxlQ01TIG1heSBiZSB1c2VkIHRvICJncm91cCIgc2V2ZXJhbCBuYW1lZCBjb2xvciBkYXRhYmFzZXMgaW50byBhIHNpbmdsZSBwcm9maWxlLgovLyBJdCBoYXMsIGhvd2V2ZXIsIHNldmVyYWwgbWlub3IgbGltaXRhdGlvbnMuIFBDUyBpcyBhbHdheXMgTGFiLCB3aGljaCBpcyBub3QgdmVyeSBjcml0aWMgc2luY2UgdGhpcwovLyBpcyB0aGUgbm9ybWFsIFBDUyBmb3IgbmFtZWQgY29sb3IgcHJvZmlsZXMuCnN0YXRpYwpjbXNIUFJPRklMRSBDcmVhdGVOYW1lZENvbG9yRGV2aWNlbGluayhjbXNIVFJBTlNGT1JNIHhmb3JtKQp7CiAgICBfY21zVFJBTlNGT1JNKiB2ID0gKF9jbXNUUkFOU0ZPUk0qKSB4Zm9ybTsKICAgIGNtc0hQUk9GSUxFIGhJQ0MgPSBOVUxMOwogICAgaW50IGksIG5Db2xvcnM7CiAgICBjbXNOQU1FRENPTE9STElTVCAqbmMyID0gTlVMTCwgKk9yaWdpbmFsID0gTlVMTDsKCiAgICAvLyBDcmVhdGUgYW4gZW1wdHkgcGxhY2Vob2xkZXIKICAgIGhJQ0MgPSBjbXNDcmVhdGVQcm9maWxlUGxhY2Vob2xkZXIodi0+Q29udGV4dElEKTsKICAgIGlmIChoSUNDID09IE5VTEwpIHJldHVybiBOVUxMOwoKICAgIC8vIENyaXRpY2FsIGluZm9ybWF0aW9uCiAgICBjbXNTZXREZXZpY2VDbGFzcyhoSUNDLCBjbXNTaWdOYW1lZENvbG9yQ2xhc3MpOwogICAgY21zU2V0Q29sb3JTcGFjZShoSUNDLCB2IC0+RXhpdENvbG9yU3BhY2UpOwogICAgY21zU2V0UENTKGhJQ0MsIGNtc1NpZ0xhYkRhdGEpOwoKICAgIC8vIFRhZyBwcm9maWxlIHdpdGggaW5mb3JtYXRpb24KICAgIGlmICghU2V0VGV4dFRhZ3MoaElDQywgTCJOYW1lZCBjb2xvciBkZXZpY2VsaW5rIikpIGdvdG8gRXJyb3I7CgogICAgT3JpZ2luYWwgPSBjbXNHZXROYW1lZENvbG9yTGlzdCh4Zm9ybSk7CiAgICBpZiAoT3JpZ2luYWwgPT0gTlVMTCkgZ290byBFcnJvcjsKCiAgICBuQ29sb3JzID0gY21zTmFtZWRDb2xvckNvdW50KE9yaWdpbmFsKTsKICAgIG5jMiAgICAgPSBjbXNEdXBOYW1lZENvbG9yTGlzdChPcmlnaW5hbCk7CiAgICBpZiAobmMyID09IE5VTEwpIGdvdG8gRXJyb3I7CgogICAgLy8gQ29sb3JhbnQgY291bnQgbm93IGRlcGVuZHMgb24gdGhlIG91dHB1dCBzcGFjZQogICAgbmMyIC0+Q29sb3JhbnRDb3VudCA9IGNtc1BpcGVsaW5lT3V0cHV0Q2hhbm5lbHModiAtPkx1dCk7CgogICAgLy8gTWFrZSBzdXJlIHdlIGhhdmUgcHJvcGVyIGZvcm1hdHRlcnMKICAgIGNtc0NoYW5nZUJ1ZmZlcnNGb3JtYXQoeGZvcm0sIFRZUEVfTkFNRURfQ09MT1JfSU5ERVgsCiAgICAgICAgRkxPQVRfU0goMCkgfCBDT0xPUlNQQUNFX1NIKF9jbXNMQ01TY29sb3JTcGFjZSh2IC0+RXhpdENvbG9yU3BhY2UpKQogICAgICAgIHwgQllURVNfU0goMikgfCBDSEFOTkVMU19TSChjbXNDaGFubmVsc09mKHYgLT5FeGl0Q29sb3JTcGFjZSkpKTsKCiAgICAvLyBBcHBseSB0aGUgdHJhbnNmb3IgdG8gY29sb3JhbnRzLgogICAgZm9yIChpPTA7IGkgPCBuQ29sb3JzOyBpKyspIHsKICAgICAgICBjbXNEb1RyYW5zZm9ybSh4Zm9ybSwgJmksIG5jMiAtPkxpc3RbaV0uRGV2aWNlQ29sb3JhbnQsIDEpOwogICAgfQoKICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnTmFtZWRDb2xvcjJUYWcsICh2b2lkKikgbmMyKSkgZ290byBFcnJvcjsKICAgIGNtc0ZyZWVOYW1lZENvbG9yTGlzdChuYzIpOwoKICAgIHJldHVybiBoSUNDOwoKRXJyb3I6CiAgICBpZiAoaElDQyAhPSBOVUxMKSBjbXNDbG9zZVByb2ZpbGUoaElDQyk7CiAgICByZXR1cm4gTlVMTDsKfQoKCi8vIFRoaXMgc3RydWN0dXJlIGhvbGRzIGluZm9ybWF0aW9uIGFib3V0IHdoaWNoIE1QVSBjYW4gYmUgc3RvcmVkIG9uIGEgcHJvZmlsZSBiYXNlZCBvbiB0aGUgdmVyc2lvbgoKdHlwZWRlZiBzdHJ1Y3QgewogICAgY21zQm9vbCAgICAgICAgICAgICAgSXNWNDsgICAgICAgICAgICAgLy8gSXMgYSBWNCB0YWc/CiAgICBjbXNUYWdTaWduYXR1cmUgICAgICBSZXF1aXJlZFRhZzsgICAgICAvLyBTZXQgdG8gMCBmb3IgYm90aCB0eXBlcwogICAgY21zVGFnVHlwZVNpZ25hdHVyZSAgTHV0VHlwZTsgICAgICAgICAgLy8gVGhlIExVVCB0eXBlCiAgICBpbnQgICAgICAgICAgICAgICAgICBuVHlwZXM7ICAgICAgICAgICAvLyBOdW1iZXIgb2YgdHlwZXMgKHVwIHRvIDUpCiAgICBjbXNTdGFnZVNpZ25hdHVyZSAgICBNcGVUeXBlc1s1XTsgICAgICAvLyA1IGlzIHRoZSBtYXhpbXVtIG51bWJlcgoKfSBjbXNBbGxvd2VkTFVUOwoKI2RlZmluZSBjbXNTaWcwICgoY21zVGFnU2lnbmF0dXJlKSAwKQoKc3RhdGljIGNvbnN0IGNtc0FsbG93ZWRMVVQgQWxsb3dlZExVVFR5cGVzW10gPSB7CgogICAgeyBGQUxTRSwgY21zU2lnMCwgICAgICAgIGNtc1NpZ0x1dDE2VHlwZSwgNCwgeyBjbXNTaWdNYXRyaXhFbGVtVHlwZSwgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnQ0x1dEVsZW1UeXBlLCBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH0gfSwKICAgIHsgRkFMU0UsIGNtc1NpZzAsICAgICAgICBjbXNTaWdMdXQxNlR5cGUsIDMsIHsgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnQ0x1dEVsZW1UeXBlLCBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH0gfSwKICAgIHsgRkFMU0UsIGNtc1NpZzAsICAgICAgICBjbXNTaWdMdXQxNlR5cGUsIDIsIHsgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnQ0x1dEVsZW1UeXBlIH0gfSwKICAgIHsgVFJVRSwgIGNtc1NpZzAsICAgICAgICBjbXNTaWdMdXRBdG9CVHlwZSwgMSwgeyBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH0gfSwKICAgIHsgVFJVRSAsIGNtc1NpZ0FUb0IwVGFnLCBjbXNTaWdMdXRBdG9CVHlwZSwgIDMsICB7IGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUsIGNtc1NpZ01hdHJpeEVsZW1UeXBlLCBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH0gfSwKICAgIHsgVFJVRSAsIGNtc1NpZ0FUb0IwVGFnLCBjbXNTaWdMdXRBdG9CVHlwZSwgIDMsICB7IGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUsIGNtc1NpZ0NMdXRFbGVtVHlwZSwgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSAgIH0gfSwKICAgIHsgVFJVRSAsIGNtc1NpZ0FUb0IwVGFnLCBjbXNTaWdMdXRBdG9CVHlwZSwgIDUsICB7IGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUsIGNtc1NpZ0NMdXRFbGVtVHlwZSwgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnTWF0cml4RWxlbVR5cGUsIGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUgfX0sCiAgICB7IFRSVUUgLCBjbXNTaWdCVG9BMFRhZywgY21zU2lnTHV0QnRvQVR5cGUsICAxLCAgeyBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH19LAogICAgeyBUUlVFICwgY21zU2lnQlRvQTBUYWcsIGNtc1NpZ0x1dEJ0b0FUeXBlLCAgMywgIHsgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnTWF0cml4RWxlbVR5cGUsIGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUgfX0sCiAgICB7IFRSVUUgLCBjbXNTaWdCVG9BMFRhZywgY21zU2lnTHV0QnRvQVR5cGUsICAzLCAgeyBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlLCBjbXNTaWdDTHV0RWxlbVR5cGUsIGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUgfX0sCiAgICB7IFRSVUUgLCBjbXNTaWdCVG9BMFRhZywgY21zU2lnTHV0QnRvQVR5cGUsICA1LCAgeyBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlLCBjbXNTaWdNYXRyaXhFbGVtVHlwZSwgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnQ0x1dEVsZW1UeXBlLCBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH19Cn07CgojZGVmaW5lIFNJWkVfT0ZfQUxMT1dFRF9MVVQgKHNpemVvZihBbGxvd2VkTFVUVHlwZXMpL3NpemVvZihjbXNBbGxvd2VkTFVUKSkKCi8vIENoZWNrIGEgc2luZ2xlIGVudHJ5CnN0YXRpYwpjbXNCb29sIENoZWNrT25lKGNvbnN0IGNtc0FsbG93ZWRMVVQqIFRhYiwgY29uc3QgY21zUGlwZWxpbmUqIEx1dCkKewogICAgY21zU3RhZ2UqIG1wZTsKICAgIGludCBuOwoKICAgIGZvciAobj0wLCBtcGUgPSBMdXQgLT5FbGVtZW50czsgbXBlICE9IE5VTEw7IG1wZSA9IG1wZSAtPk5leHQsIG4rKykgewoKICAgICAgICBpZiAobiA+IFRhYiAtPm5UeXBlcykgcmV0dXJuIEZBTFNFOwogICAgICAgIGlmIChjbXNTdGFnZVR5cGUobXBlKSAhPSBUYWIgLT5NcGVUeXBlc1tuXSkgcmV0dXJuIEZBTFNFOwogICAgfQoKICAgIHJldHVybiAobiA9PSBUYWIgLT5uVHlwZXMpOwp9CgoKc3RhdGljCmNvbnN0IGNtc0FsbG93ZWRMVVQqIEZpbmRDb21iaW5hdGlvbihjb25zdCBjbXNQaXBlbGluZSogTHV0LCBjbXNCb29sIElzVjQsIGNtc1RhZ1NpZ25hdHVyZSBEZXN0aW5hdGlvblRhZykKewogICAgY21zVUludDMyTnVtYmVyIG47CgogICAgZm9yIChuPTA7IG4gPCBTSVpFX09GX0FMTE9XRURfTFVUOyBuKyspIHsKCiAgICAgICAgY29uc3QgY21zQWxsb3dlZExVVCogVGFiID0gQWxsb3dlZExVVFR5cGVzICsgbjsKCiAgICAgICAgaWYgKElzVjQgXiBUYWIgLT4gSXNWNCkgY29udGludWU7CiAgICAgICAgaWYgKChUYWIgLT5SZXF1aXJlZFRhZyAhPSAwKSAmJiAoVGFiIC0+UmVxdWlyZWRUYWcgIT0gRGVzdGluYXRpb25UYWcpKSBjb250aW51ZTsKCiAgICAgICAgaWYgKENoZWNrT25lKFRhYiwgTHV0KSkgcmV0dXJuIFRhYjsKICAgIH0KCiAgICByZXR1cm4gTlVMTDsKfQoKCi8vIERvZXMgY29udmVydCBhIHRyYW5zZm9ybSBpbnRvIGEgZGV2aWNlIGxpbmsgcHJvZmlsZQpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zVHJhbnNmb3JtMkRldmljZUxpbmsoY21zSFRSQU5TRk9STSBoVHJhbnNmb3JtLCBjbXNGbG9hdDY0TnVtYmVyIFZlcnNpb24sIGNtc1VJbnQzMk51bWJlciBkd0ZsYWdzKQp7CiAgICBjbXNIUFJPRklMRSBoUHJvZmlsZSA9IE5VTEw7CiAgICBjbXNVSW50MzJOdW1iZXIgRnJtSW4sIEZybU91dCwgQ2hhbnNJbiwgQ2hhbnNPdXQ7CiAgICBjbXNVSW50MzJOdW1iZXIgQ29sb3JTcGFjZUJpdHNJbiwgQ29sb3JTcGFjZUJpdHNPdXQ7CiAgICBfY21zVFJBTlNGT1JNKiB4Zm9ybSA9IChfY21zVFJBTlNGT1JNKikgaFRyYW5zZm9ybTsKICAgIGNtc1BpcGVsaW5lKiBMVVQgPSBOVUxMOwogICAgY21zU3RhZ2UqIG1wZTsKICAgIGNtc0NvbnRleHQgQ29udGV4dElEID0gY21zR2V0VHJhbnNmb3JtQ29udGV4dElEKGhUcmFuc2Zvcm0pOwogICAgY29uc3QgY21zQWxsb3dlZExVVCogQWxsb3dlZExVVDsKICAgIGNtc1RhZ1NpZ25hdHVyZSBEZXN0aW5hdGlvblRhZzsKICAgIGNtc1Byb2ZpbGVDbGFzc1NpZ25hdHVyZSBkZXZpY2VDbGFzczsKCiAgICBfY21zQXNzZXJ0KGhUcmFuc2Zvcm0gIT0gTlVMTCk7CgogICAgLy8gR2V0IHRoZSBmaXJzdCBtcGUgdG8gY2hlY2sgZm9yIG5hbWVkIGNvbG9yCiAgICBtcGUgPSBjbXNQaXBlbGluZUdldFB0clRvRmlyc3RTdGFnZSh4Zm9ybSAtPkx1dCk7CgogICAgLy8gQ2hlY2sgaWYgaXMgYSBuYW1lZCBjb2xvciB0cmFuc2Zvcm0KICAgIGlmIChtcGUgIT0gTlVMTCkgewoKICAgICAgICBpZiAoY21zU3RhZ2VUeXBlKG1wZSkgPT0gY21zU2lnTmFtZWRDb2xvckVsZW1UeXBlKSB7CiAgICAgICAgICAgIHJldHVybiBDcmVhdGVOYW1lZENvbG9yRGV2aWNlbGluayhoVHJhbnNmb3JtKTsKICAgICAgICB9CiAgICB9CgogICAgLy8gRmlyc3QgdGhpbmcgdG8gZG8gaXMgdG8gZ2V0IGEgY29weSBvZiB0aGUgdHJhbnNmb3JtYXRpb24KICAgIExVVCA9IGNtc1BpcGVsaW5lRHVwKHhmb3JtIC0+THV0KTsKICAgIGlmIChMVVQgPT0gTlVMTCkgcmV0dXJuIE5VTEw7CgogICAgLy8gVGltZSB0byBmaXggdGhlIExhYjIvTGFiNCBpc3N1ZS4KICAgIGlmICgoeGZvcm0gLT5FbnRyeUNvbG9yU3BhY2UgPT0gY21zU2lnTGFiRGF0YSkgJiYgKFZlcnNpb24gPCA0LjApKSB7CgogICAgICAgIGlmICghY21zUGlwZWxpbmVJbnNlcnRTdGFnZShMVVQsIGNtc0FUX0JFR0lOLCBfY21zU3RhZ2VBbGxvY0xhYlYyVG9WNGN1cnZlcyhDb250ZXh0SUQpKSkKICAgICAgICAgICAgZ290byBFcnJvcjsKICAgIH0KCiAgICAvLyBPbiB0aGUgb3V0cHV0IHNpZGUgdG9vCiAgICBpZiAoKHhmb3JtIC0+RXhpdENvbG9yU3BhY2UpID09IGNtc1NpZ0xhYkRhdGEgJiYgKFZlcnNpb24gPCA0LjApKSB7CgogICAgICAgIGlmICghY21zUGlwZWxpbmVJbnNlcnRTdGFnZShMVVQsIGNtc0FUX0VORCwgX2Ntc1N0YWdlQWxsb2NMYWJWNFRvVjIoQ29udGV4dElEKSkpCiAgICAgICAgICAgIGdvdG8gRXJyb3I7CiAgICB9CgoKICAgIGhQcm9maWxlID0gY21zQ3JlYXRlUHJvZmlsZVBsYWNlaG9sZGVyKENvbnRleHRJRCk7CiAgICBpZiAoIWhQcm9maWxlKSBnb3RvIEVycm9yOyAgICAgICAgICAgICAgICAgICAgLy8gY2FuJ3QgYWxsb2NhdGUKCiAgICBjbXNTZXRQcm9maWxlVmVyc2lvbihoUHJvZmlsZSwgVmVyc2lvbik7CgogICAgRml4Q29sb3JTcGFjZXMoaFByb2ZpbGUsIHhmb3JtIC0+IEVudHJ5Q29sb3JTcGFjZSwgeGZvcm0gLT4gRXhpdENvbG9yU3BhY2UsIGR3RmxhZ3MpOwoKICAgIC8vIE9wdGltaXplIHRoZSBMVVQgYW5kIHByZWNhbGN1bGF0ZSBhIGRldmljZWxpbmsKCiAgICBDaGFuc0luICA9IGNtc0NoYW5uZWxzT2YoeGZvcm0gLT4gRW50cnlDb2xvclNwYWNlKTsKICAgIENoYW5zT3V0ID0gY21zQ2hhbm5lbHNPZih4Zm9ybSAtPiBFeGl0Q29sb3JTcGFjZSk7CgogICAgQ29sb3JTcGFjZUJpdHNJbiAgPSBfY21zTENNU2NvbG9yU3BhY2UoeGZvcm0gLT4gRW50cnlDb2xvclNwYWNlKTsKICAgIENvbG9yU3BhY2VCaXRzT3V0ID0gX2Ntc0xDTVNjb2xvclNwYWNlKHhmb3JtIC0+IEV4aXRDb2xvclNwYWNlKTsKCiAgICBGcm1JbiAgPSBDT0xPUlNQQUNFX1NIKENvbG9yU3BhY2VCaXRzSW4pIHwgQ0hBTk5FTFNfU0goQ2hhbnNJbil8QllURVNfU0goMik7CiAgICBGcm1PdXQgPSBDT0xPUlNQQUNFX1NIKENvbG9yU3BhY2VCaXRzT3V0KSB8IENIQU5ORUxTX1NIKENoYW5zT3V0KXxCWVRFU19TSCgyKTsKCiAgICBkZXZpY2VDbGFzcyA9IGNtc0dldERldmljZUNsYXNzKGhQcm9maWxlKTsKCiAgICAgaWYgKGRldmljZUNsYXNzID09IGNtc1NpZ091dHB1dENsYXNzKQogICAgICAgICBEZXN0aW5hdGlvblRhZyA9IGNtc1NpZ0JUb0EwVGFnOwogICAgIGVsc2UKICAgICAgICAgRGVzdGluYXRpb25UYWcgPSBjbXNTaWdBVG9CMFRhZzsKCiAgICAvLyBDaGVjayBpZiB0aGUgcHJvZmlsZS92ZXJzaW9uIGNhbiBzdG9yZSB0aGUgcmVzdWx0CiAgICBpZiAoZHdGbGFncyAmIGNtc0ZMQUdTX0ZPUkNFX0NMVVQpCiAgICAgICAgQWxsb3dlZExVVCA9IE5VTEw7CiAgICBlbHNlCiAgICAgICAgQWxsb3dlZExVVCA9IEZpbmRDb21iaW5hdGlvbihMVVQsIFZlcnNpb24gPj0gNC4wLCBEZXN0aW5hdGlvblRhZyk7CgogICAgaWYgKEFsbG93ZWRMVVQgPT0gTlVMTCkgewoKICAgICAgICAvLyBUcnkgdG8gb3B0aW1pemUKICAgICAgICBfY21zT3B0aW1pemVQaXBlbGluZShDb250ZXh0SUQsICZMVVQsIHhmb3JtIC0+UmVuZGVyaW5nSW50ZW50LCAmRnJtSW4sICZGcm1PdXQsICZkd0ZsYWdzKTsKICAgICAgICBBbGxvd2VkTFVUID0gRmluZENvbWJpbmF0aW9uKExVVCwgVmVyc2lvbiA+PSA0LjAsIERlc3RpbmF0aW9uVGFnKTsKCiAgICB9CgogICAgLy8gSWYgbm8gd2F5LCB0aGVuIGZvcmNlIENMVVQgdGhhdCBmb3Igc3VyZSBjYW4gYmUgd3JpdHRlbgogICAgaWYgKEFsbG93ZWRMVVQgPT0gTlVMTCkgewoKICAgICAgICBkd0ZsYWdzIHw9IGNtc0ZMQUdTX0ZPUkNFX0NMVVQ7CiAgICAgICAgX2Ntc09wdGltaXplUGlwZWxpbmUoQ29udGV4dElELCAmTFVULCB4Zm9ybSAtPlJlbmRlcmluZ0ludGVudCwgJkZybUluLCAmRnJtT3V0LCAmZHdGbGFncyk7CgogICAgICAgIC8vIFB1dCBpZGVudGl0eSBjdXJ2ZXMgaWYgbmVlZGVkCiAgICAgICAgaWYgKGNtc1BpcGVsaW5lR2V0UHRyVG9GaXJzdFN0YWdlKExVVCkgLT5UeXBlICE9IGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUpCiAgICAgICAgICAgICBpZiAoIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9CRUdJTiwgX2Ntc1N0YWdlQWxsb2NJZGVudGl0eUN1cnZlcyhDb250ZXh0SUQsIENoYW5zSW4pKSkKICAgICAgICAgICAgICAgICBnb3RvIEVycm9yOwoKICAgICAgICBpZiAoY21zUGlwZWxpbmVHZXRQdHJUb0xhc3RTdGFnZShMVVQpIC0+VHlwZSAhPSBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlKQogICAgICAgICAgICAgaWYgKCFjbXNQaXBlbGluZUluc2VydFN0YWdlKExVVCwgY21zQVRfRU5ELCAgIF9jbXNTdGFnZUFsbG9jSWRlbnRpdHlDdXJ2ZXMoQ29udGV4dElELCBDaGFuc091dCkpKQogICAgICAgICAgICAgICAgIGdvdG8gRXJyb3I7CgogICAgICAgIEFsbG93ZWRMVVQgPSBGaW5kQ29tYmluYXRpb24oTFVULCBWZXJzaW9uID49IDQuMCwgRGVzdGluYXRpb25UYWcpOwogICAgfQoKICAgIC8vIFNvbWV0aGluZ3MgaXMgd3JvbmcuLi4KICAgIGlmIChBbGxvd2VkTFVUID09IE5VTEwpIHsKICAgICAgICBnb3RvIEVycm9yOwogICAgfQoKCiAgICBpZiAoZHdGbGFncyAmIGNtc0ZMQUdTXzhCSVRTX0RFVklDRUxJTkspCiAgICAgICAgICAgICAgICAgICAgIGNtc1BpcGVsaW5lU2V0U2F2ZUFzOGJpdHNGbGFnKExVVCwgVFJVRSk7CgogICAgLy8gVGFnIHByb2ZpbGUgd2l0aCBpbmZvcm1hdGlvbgogICAgaWYgKCFTZXRUZXh0VGFncyhoUHJvZmlsZSwgTCJkZXZpY2VsaW5rIikpIGdvdG8gRXJyb3I7CgogICAgLy8gU3RvcmUgcmVzdWx0CiAgICBpZiAoIWNtc1dyaXRlVGFnKGhQcm9maWxlLCBEZXN0aW5hdGlvblRhZywgTFVUKSkgZ290byBFcnJvcjsKCgogICAgaWYgKHhmb3JtIC0+IElucHV0Q29sb3JhbnQgIT0gTlVMTCkgewogICAgICAgICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIGNtc1NpZ0NvbG9yYW50VGFibGVUYWcsIHhmb3JtLT5JbnB1dENvbG9yYW50KSkgZ290byBFcnJvcjsKICAgIH0KCiAgICBpZiAoeGZvcm0gLT4gT3V0cHV0Q29sb3JhbnQgIT0gTlVMTCkgewogICAgICAgICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIGNtc1NpZ0NvbG9yYW50VGFibGVPdXRUYWcsIHhmb3JtLT5PdXRwdXRDb2xvcmFudCkpIGdvdG8gRXJyb3I7CiAgICB9CgogICAgaWYgKChkZXZpY2VDbGFzcyA9PSBjbXNTaWdMaW5rQ2xhc3MpICYmICh4Zm9ybSAtPlNlcXVlbmNlICE9IE5VTEwpKSB7CiAgICAgICAgaWYgKCFfY21zV3JpdGVQcm9maWxlU2VxdWVuY2UoaFByb2ZpbGUsIHhmb3JtIC0+U2VxdWVuY2UpKSBnb3RvIEVycm9yOwogICAgfQoKICAgIC8vIFNldCB0aGUgd2hpdGUgcG9pbnQKICAgIGlmIChkZXZpY2VDbGFzcyA9PSBjbXNTaWdJbnB1dENsYXNzKSB7CiAgICAgICAgaWYgKCFjbXNXcml0ZVRhZyhoUHJvZmlsZSwgY21zU2lnTWVkaWFXaGl0ZVBvaW50VGFnLCAmeGZvcm0gLT5FbnRyeVdoaXRlUG9pbnQpKSBnb3RvIEVycm9yOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIGNtc1NpZ01lZGlhV2hpdGVQb2ludFRhZywgJnhmb3JtIC0+RXhpdFdoaXRlUG9pbnQpKSBnb3RvIEVycm9yOwogICAgfQoKCiAgICAvLyBQZXIgNy4yLjE1IGluIHNwZWMgNC4zCiAgICBjbXNTZXRIZWFkZXJSZW5kZXJpbmdJbnRlbnQoaFByb2ZpbGUsIHhmb3JtIC0+UmVuZGVyaW5nSW50ZW50KTsKCiAgICBjbXNQaXBlbGluZUZyZWUoTFVUKTsKICAgIHJldHVybiBoUHJvZmlsZTsKCkVycm9yOgogICAgaWYgKExVVCAhPSBOVUxMKSBjbXNQaXBlbGluZUZyZWUoTFVUKTsKICAgIGNtc0Nsb3NlUHJvZmlsZShoUHJvZmlsZSk7CiAgICByZXR1cm4gTlVMTDsKfQo=