I2lmbmRlZiBHSU1fQ09OVEFDVF9IX0lOQ0xVREVECiNkZWZpbmUgR0lNX0NPTlRBQ1RfSF9JTkNMVURFRAoKLyohIFxmaWxlIGdpbV9jb250YWN0LmgKXGF1dGhvciBGcmFuY2lzY28gTGV/biBO32plcmEKKi8KLyoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KVGhpcyBzb3VyY2UgZmlsZSBpcyBwYXJ0IG9mIEdJTVBBQ1QgTGlicmFyeS4KCkZvciB0aGUgbGF0ZXN0IGluZm8sIHNlZSBodHRwOi8vZ2ltcGFjdC5zb3VyY2Vmb3JnZS5uZXQvCgpDb3B5cmlnaHQgKGMpIDIwMDYgRnJhbmNpc2NvIExlb24gTmFqZXJhLiBDLkMuIDgwMDg3MzcxLgplbWFpbDogcHJvamVjdGlsZW1hbkB5YWhvby5jb20KCiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIEVJVEhFUjoKICAgKDEpIFRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlCiAgICAgICBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdAogICAgICAgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLiBUaGUgdGV4dCBvZiB0aGUgR05VIExlc3NlcgogICAgICAgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBpcyBpbmNsdWRlZCB3aXRoIHRoaXMgbGlicmFyeSBpbiB0aGUKICAgICAgIGZpbGUgR0lNUEFDVC1MSUNFTlNFLUxHUEwuVFhULgogICAoMikgVGhlIEJTRC1zdHlsZSBsaWNlbnNlIHRoYXQgaXMgaW5jbHVkZWQgd2l0aCB0aGlzIGxpYnJhcnkgaW4KICAgICAgIHRoZSBmaWxlIEdJTVBBQ1QtTElDRU5TRS1CU0QuVFhULgogICAoMykgVGhlIHpsaWIvbGlicG5nIGxpY2Vuc2UgdGhhdCBpcyBpbmNsdWRlZCB3aXRoIHRoaXMgbGlicmFyeSBpbgogICAgICAgdGhlIGZpbGUgR0lNUEFDVC1MSUNFTlNFLVpMSUIuVFhULgoKIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBmaWxlcwogR0lNUEFDVC1MSUNFTlNFLUxHUEwuVFhULCBHSU1QQUNULUxJQ0VOU0UtWkxJQi5UWFQgYW5kIEdJTVBBQ1QtTElDRU5TRS1CU0QuVFhUIGZvciBtb3JlIGRldGFpbHMuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoqLwojaW5jbHVkZSAiZ2ltX2dlb21ldHJ5LmgiCiNpbmNsdWRlICJnaW1fcmFkaXhzb3J0LmgiCiNpbmNsdWRlICJnaW1fYXJyYXkuaCIKCgovKioKQ29uZmlndXJhdGlvbiB2YXIgZm9yIGFwcGx5aW5nIGludGVycG9sYXRpb24gb2YgIGNvbnRhY3Qgbm9ybWFscwoqLwojZGVmaW5lIE5PUk1BTF9DT05UQUNUX0FWRVJBR0UgMQojZGVmaW5lIENPTlRBQ1RfRElGRl9FUFNJTE9OIDAuMDAwMDFmCgovLy8gU3RydWN0dXJlIGZvciBjb2xsaXNpb24gcmVzdWx0cwovLy9GdW5jdGlvbnMgZm9yIG1hbmFnaW5nIGFuZCBzb3J0aW5nIGNvbnRhY3RzIHJlc3VsdGluZyBmcm9tIGEgY29sbGlzaW9uIHF1ZXJ5LgovLy9Db250YWN0IGxpc3RzIG11c3QgYmUgY3JlYXRlIGJ5IGNhbGxpbmcgXHJlZiBHSU1fQ1JFQVRFX0NPTlRBQ1RfTElTVAovLy9BZnRlciBxdWVyeXMsIGNvbnRhY3QgbGlzdHMgbXVzdCBiZSBkZXN0cm95IGJ5IGNhbGxpbmcgXHJlZiBHSU1fRFlOQVJSQVlfREVTVFJPWQovLy9Db250YWN0cyBjYW4gYmUgbWVyZ2UgZm9yIGF2b2lkIGR1cGxpY2F0ZSByZXN1bHRzIGJ5IGNhbGxpbmcgXHJlZiBnaW1fbWVyZ2VfY29udGFjdHMKY2xhc3MgR0lNX0NPTlRBQ1QKewpwdWJsaWM6CiAgICBidFZlY3RvcjMgbV9wb2ludDsKICAgIGJ0VmVjdG9yMyBtX25vcm1hbDsKICAgIEdSRUFMIG1fZGVwdGg7Ly9Qb3NpdGl2ZSB2YWx1ZSBpbmRpY2F0ZXMgaW50ZXJwZW5ldHJhdGlvbgogICAgR1JFQUwgbV9kaXN0YW5jZTsvL1BhZGRpbmcgbm90IGZvciB1c2UKICAgIEdVSU5UIG1fZmVhdHVyZTE7Ly9GYWNlIG51bWJlcgogICAgR1VJTlQgbV9mZWF0dXJlMjsvL0ZhY2UgbnVtYmVyCnB1YmxpYzoKICAgIEdJTV9DT05UQUNUKCkKICAgIHsKICAgIH0KCiAgICBHSU1fQ09OVEFDVChjb25zdCBHSU1fQ09OVEFDVCAmIGNvbnRhY3QpOgoJCQkJbV9wb2ludChjb250YWN0Lm1fcG9pbnQpLAoJCQkJbV9ub3JtYWwoY29udGFjdC5tX25vcm1hbCksCgkJCQltX2RlcHRoKGNvbnRhY3QubV9kZXB0aCksCgkJCQltX2ZlYXR1cmUxKGNvbnRhY3QubV9mZWF0dXJlMSksCgkJCQltX2ZlYXR1cmUyKGNvbnRhY3QubV9mZWF0dXJlMikKICAgIHsKICAgIAltX3BvaW50ID0gY29udGFjdC5tX3BvaW50OwogICAgCW1fbm9ybWFsID0gY29udGFjdC5tX25vcm1hbDsKICAgIAltX2RlcHRoID0gY29udGFjdC5tX2RlcHRoOwogICAgCW1fZmVhdHVyZTEgPSBjb250YWN0Lm1fZmVhdHVyZTE7CiAgICAJbV9mZWF0dXJlMiA9IGNvbnRhY3QubV9mZWF0dXJlMjsKICAgIH0KCiAgICBHSU1fQ09OVEFDVChjb25zdCBidFZlY3RvcjMgJnBvaW50LGNvbnN0IGJ0VmVjdG9yMyAmIG5vcm1hbCwKICAgIAkgCQkJR1JFQUwgZGVwdGgsIEdVSU5UIGZlYXR1cmUxLCBHVUlOVCBmZWF0dXJlMik6CgkJCQltX3BvaW50KHBvaW50KSwKCQkJCW1fbm9ybWFsKG5vcm1hbCksCgkJCQltX2RlcHRoKGRlcHRoKSwKCQkJCW1fZmVhdHVyZTEoZmVhdHVyZTEpLAoJCQkJbV9mZWF0dXJlMihmZWF0dXJlMikKICAgIHsKICAgIH0KCgkvLyEgQ2FsY3Mga2V5IGZvciBjb29yZCBjbGFzc2lmaWNhdGlvbgogICAgU0lNRF9GT1JDRV9JTkxJTkUgR1VJTlQgY2FsY19rZXlfY29udGFjdCgpIGNvbnN0CiAgICB7CiAgICAJR0lOVCBfY29vcmRzW10gPSB7CiAgICAJCShHSU5UKShtX3BvaW50WzBdKjEwMDAuMGYrMS4wZiksCiAgICAJCShHSU5UKShtX3BvaW50WzFdKjEzMzMuMGYpLAogICAgCQkoR0lOVCkobV9wb2ludFsyXSoyMTMzLjBmKzMuMGYpfTsKCQlHVUlOVCBfaGFzaD0wOwoJCUdVSU5UICpfdWl0bXAgPSAoR1VJTlQgKikoJl9jb29yZHNbMF0pOwoJCV9oYXNoID0gKl91aXRtcDsKCQlfdWl0bXArKzsKCQlfaGFzaCArPSAoKl91aXRtcCk8PDQ7CgkJX3VpdG1wKys7CgkJX2hhc2ggKz0gKCpfdWl0bXApPDw4OwoJCXJldHVybiBfaGFzaDsKICAgIH0KCiAgICBTSU1EX0ZPUkNFX0lOTElORSB2b2lkIGludGVycG9sYXRlX25vcm1hbHMoIGJ0VmVjdG9yMyAqIG5vcm1hbHMsR1VJTlQgbm9ybWFsX2NvdW50KQogICAgewogICAgCWJ0VmVjdG9yMyB2ZWNfc3VtKG1fbm9ybWFsKTsKCQlmb3IoR1VJTlQgaT0wO2k8bm9ybWFsX2NvdW50O2krKykKCQl7CgkJCXZlY19zdW0gKz0gbm9ybWFsc1tpXTsKCQl9CgoJCUdSRUFMIHZlY19zdW1fbGVuID0gdmVjX3N1bS5sZW5ndGgyKCk7CgkJaWYodmVjX3N1bV9sZW4gPENPTlRBQ1RfRElGRl9FUFNJTE9OKSByZXR1cm47CgoJCUdJTV9JTlZfU1FSVCh2ZWNfc3VtX2xlbix2ZWNfc3VtX2xlbik7IC8vIDEvc3FydCh2ZWNfc3VtX2xlbikKCgkJbV9ub3JtYWwgPSB2ZWNfc3VtKnZlY19zdW1fbGVuOwogICAgfQoKfTsKCgpjbGFzcyBnaW1fY29udGFjdF9hcnJheTpwdWJsaWMgZ2ltX2FycmF5PEdJTV9DT05UQUNUPgp7CnB1YmxpYzoKCWdpbV9jb250YWN0X2FycmF5KCk6Z2ltX2FycmF5PEdJTV9DT05UQUNUPig2NCkKCXsKCX0KCglTSU1EX0ZPUkNFX0lOTElORSB2b2lkIHB1c2hfY29udGFjdChjb25zdCBidFZlY3RvcjMgJnBvaW50LGNvbnN0IGJ0VmVjdG9yMyAmIG5vcm1hbCwKICAgIAkgCQkJR1JFQUwgZGVwdGgsIEdVSU5UIGZlYXR1cmUxLCBHVUlOVCBmZWF0dXJlMikKCXsKCQlwdXNoX2JhY2tfbWVtKCk7CgkJR0lNX0NPTlRBQ1QgJiBuZXdlbGUgPSBiYWNrKCk7CgkJbmV3ZWxlLm1fcG9pbnQgPSBwb2ludDsKCQluZXdlbGUubV9ub3JtYWwgPSBub3JtYWw7CgkJbmV3ZWxlLm1fZGVwdGggPSBkZXB0aDsKCQluZXdlbGUubV9mZWF0dXJlMSA9IGZlYXR1cmUxOwoJCW5ld2VsZS5tX2ZlYXR1cmUyID0gZmVhdHVyZTI7Cgl9CgoJU0lNRF9GT1JDRV9JTkxJTkUgdm9pZCBwdXNoX3RyaWFuZ2xlX2NvbnRhY3RzKAoJCWNvbnN0IEdJTV9UUklBTkdMRV9DT05UQUNUX0RBVEEgJiB0cmljb250YWN0LAoJCUdVSU5UIGZlYXR1cmUxLEdVSU5UIGZlYXR1cmUyKQoJewoJCWZvcihHVUlOVCBpID0gMDtpPHRyaWNvbnRhY3QubV9wb2ludF9jb3VudCA7aSsrICkKCQl7CgkJCXB1c2hfYmFja19tZW0oKTsKCQkJR0lNX0NPTlRBQ1QgJiBuZXdlbGUgPSBiYWNrKCk7CgkJCW5ld2VsZS5tX3BvaW50ID0gdHJpY29udGFjdC5tX3BvaW50c1tpXTsKCQkJbmV3ZWxlLm1fbm9ybWFsID0gdHJpY29udGFjdC5tX3NlcGFyYXRpbmdfbm9ybWFsOwoJCQluZXdlbGUubV9kZXB0aCA9IHRyaWNvbnRhY3QubV9wZW5ldHJhdGlvbl9kZXB0aDsKCQkJbmV3ZWxlLm1fZmVhdHVyZTEgPSBmZWF0dXJlMTsKCQkJbmV3ZWxlLm1fZmVhdHVyZTIgPSBmZWF0dXJlMjsKCQl9Cgl9CgoJdm9pZCBtZXJnZV9jb250YWN0cyhjb25zdCBnaW1fY29udGFjdF9hcnJheSAmIGNvbnRhY3RzLCBib29sIG5vcm1hbF9jb250YWN0X2F2ZXJhZ2UgPSB0cnVlKTsKCXZvaWQgbWVyZ2VfY29udGFjdHNfdW5pcXVlKGNvbnN0IGdpbV9jb250YWN0X2FycmF5ICYgY29udGFjdHMpOwp9OwoKI2VuZGlmIC8vIEdJTV9DT05UQUNUX0hfSU5DTFVERUQK