LyoKICogTkRBIEFORCBORUVELVRPLUtOT1cgUkVRVUlSRUQKICoKICogQ29weXJpZ2h0IKkgMjAxMy0yMDE4IFN5bmFwdGljcyBJbmNvcnBvcmF0ZWQuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiAqCiAqIFRoaXMgZmlsZSBjb250YWlucyBpbmZvcm1hdGlvbiB0aGF0IGlzIHByb3ByaWV0YXJ5IHRvIFN5bmFwdGljcwogKiBJbmNvcnBvcmF0ZWQgKCJTeW5hcHRpY3MiKS4gVGhlIGhvbGRlciBvZiB0aGlzIGZpbGUgc2hhbGwgdHJlYXQgYWxsCiAqIGluZm9ybWF0aW9uIGNvbnRhaW5lZCBoZXJlaW4gYXMgY29uZmlkZW50aWFsLCBzaGFsbCB1c2UgdGhlCiAqIGluZm9ybWF0aW9uIG9ubHkgZm9yIGl0cyBpbnRlbmRlZCBwdXJwb3NlLCBhbmQgc2hhbGwgbm90IGR1cGxpY2F0ZSwKICogZGlzY2xvc2UsIG9yIGRpc3NlbWluYXRlIGFueSBvZiB0aGlzIGluZm9ybWF0aW9uIGluIGFueSBtYW5uZXIKICogdW5sZXNzIFN5bmFwdGljcyBoYXMgb3RoZXJ3aXNlIHByb3ZpZGVkIGV4cHJlc3MsIHdyaXR0ZW4KICogcGVybWlzc2lvbi4KICoKICogVXNlIG9mIHRoZSBtYXRlcmlhbHMgbWF5IHJlcXVpcmUgYSBsaWNlbnNlIG9mIGludGVsbGVjdHVhbCBwcm9wZXJ0eQogKiBmcm9tIGEgdGhpcmQgcGFydHkgb3IgZnJvbSBTeW5hcHRpY3MuIFRoaXMgZmlsZSBjb252ZXlzIG5vIGV4cHJlc3MKICogb3IgaW1wbGllZCBsaWNlbnNlcyB0byBhbnkgaW50ZWxsZWN0dWFsIHByb3BlcnR5IHJpZ2h0cyBiZWxvbmdpbmcKICogdG8gU3luYXB0aWNzLgogKgogKiBJTkZPUk1BVElPTiBDT05UQUlORUQgSU4gVEhJUyBET0NVTUVOVCBJUyBQUk9WSURFRCAiQVMtSVMsIiBBTkQKICogU1lOQVBUSUNTIEVYUFJFU1NMWSBESVNDTEFJTVMgQUxMIEVYUFJFU1MgQU5EIElNUExJRUQgV0FSUkFOVElFUywKICogSU5DTFVESU5HIEFOWSBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUgogKiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSwgQU5EIEFOWSBXQVJSQU5USUVTIE9GIE5PTi1JTkZSSU5HRU1FTlQgT0YgQU5ZCiAqIElOVEVMTEVDVFVBTCBQUk9QRVJUWSBSSUdIVFMuIElOIE5PIEVWRU5UIFNIQUxMIFNZTkFQVElDUyBCRSBMSUFCTEUKICogRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBQVU5JVElWRSwgT1IKICogQ09OU0VRVUVOVElBTCBEQU1BR0VTIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFCiAqIE9GIFRIRSBJTkZPUk1BVElPTiBDT05UQUlORUQgSU4gVEhJUyBET0NVTUVOVCwgSE9XRVZFUiBDQVVTRUQgQU5ECiAqIEJBU0VEIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwKICogTkVHTElHRU5DRSBPUiBPVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFORCBFVkVOIElGIFNZTkFQVElDUyBXQVMKICogQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuIElGIEEgVFJJQlVOQUwgT0YKICogQ09NUEVURU5UIEpVUklTRElDVElPTiBET0VTIE5PVCBQRVJNSVQgVEhFIERJU0NMQUlNRVIgT0YgRElSRUNUCiAqIERBTUFHRVMgT1IgQU5ZIE9USEVSIERBTUFHRVMsIFNZTkFQVElDUycgVE9UQUwgQ1VNVUxBVElWRSBMSUFCSUxJVFkKICogVE8gQU5ZIFBBUlRZIFNIQUxMIE5PVCBFWENFRUQgT05FIEhVTkRSRUQgVS5TLiBET0xMQVJTLgogKi8KI2luY2x1ZGUgImkyY19kcml2ZXIuaCIKI2luY2x1ZGUgImdsb2JhbC5oIgojaW5jbHVkZSAiaW8uaCIKI2luY2x1ZGUgImRlYnVnLmgiCiNpbmNsdWRlICJtZW1tYXAuaCIKI2luY2x1ZGUgImNoaXBfdm9sdGFnZV9pbmZvLmgiCiNpbmNsdWRlICJTeXNNZ3IuaCIKI2luY2x1ZGUgImFwYlJlZ0Jhc2UuaCIKI2luY2x1ZGUgImFwYl90aW1lci5oIgojaW5jbHVkZSAibGdwbF9wcmludGYuaCIKCiNpbmNsdWRlICJwdl9jb21wLmgiCgpleHRlcm4gdm9pZCBkZWxheV9tcyh1bnNpZ25lZCBpbnQgbXMpOwoKI2lmbmRlZiBWT1VUX0NQVV9JRAojZGVmaW5lIFZPVVRfQ1BVX0lEICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMikKI2VuZGlmCgojaWZuZGVmIFZPVVRfQ09SRV9JRAojZGVmaW5lIFZPVVRfQ09SRV9JRCAgICAgICAgICAgICAgICAgICAgKDApCiNlbmRpZgoKI2lmbmRlZiBWT1VUX0NQVV9DSEFOTkVMCiNkZWZpbmUgVk9VVF9DUFVfQ0hBTk5FTCAgICAgICAgICAgICAgICAoMCkKI2VuZGlmCgojaWZuZGVmIFZPVVRfQ09SRV9DSEFOTkVMCiNkZWZpbmUgVk9VVF9DT1JFX0NIQU5ORUwgICAgICAgICAgICAgICAoMSkKI2VuZGlmCgovLyBhbGwgZGVmaW5lZCB1bmRlciB1dgojaWZuZGVmIE1JTklNQUxfVk9MX1NURVBfTkNQNjMzNUQKI2RlZmluZSBNSU5JTUFMX1ZPTF9TVEVQX05DUDYzMzVEIDI1MDAwCiNlbmRpZgojZGVmaW5lIE1JTl9WT0xUQUdFIDYwMDAwMAojZGVmaW5lIE1BWF9WT0xUQUdFIDEzNzUwMDAKCiNkZWZpbmUgU0xBVkVfQUREUiAweDAKCmV4dGVybiB2b2lkIHVkZWxheSh1bnNpZ25lZCBsb25nIHVzZWMpOwpleHRlcm4gaW50IGkyY19tYXN0ZXJfaW5pdChpbnQgaWQsIGludCBzcGVlZCwgaW50IGJfMTBiaXRfYWRkcik7CmV4dGVybiBpbnQgaTJjX21hc3Rlcl93cml0ZV9hbmRfcmVhZChpbnQgaWQsIGludCB0YXJnZXRfYWRkciwgdW5zaWduZWQgY2hhciogc2VuZF9idWZmLCBpbnQgc2VuZF9sZW4sIHVuc2lnbmVkIGNoYXIqIHJlY3ZfYnVmZiwgaW50IHJlY3ZfbGVuKTsKCnN0YXRpYyBpbnQgcG1pY192b2x0MmRhdGEoaW50IHZvbHQsIHVuc2lnbmVkIGNoYXIgKnBfZGF0YSkKewoJdW5zaWduZWQgY2hhciBkYXRhOwoKCWlmICgodm9sdCA+PSBNSU5fVk9MVEFHRSkgJiYgKHZvbHQgPD0gTUFYX1ZPTFRBR0UpKQoJCWRhdGEgPSAoKHZvbHQgLSBNSU5fVk9MVEFHRSkvTUlOSU1BTF9WT0xfU1RFUF9OQ1A2MzM1RCkqNDsKCWVsc2UKCQlyZXR1cm4gLTE7CgoJZGF0YSA9IGRhdGEgJiAweDdmOwoJKnBfZGF0YSA9IGRhdGE7CglyZXR1cm4gMDsKfQoKc3RhdGljIGludCBwbWljX2RhdGEydm9sdChpbnQgKnBfdm9sdCwgdW5zaWduZWQgY2hhciB2ZGF0YSkKewoJKnBfdm9sdCA9ICgodmRhdGEgLyA0KSAqIE1JTklNQUxfVk9MX1NURVBfTkNQNjMzNUQgKyBNSU5fVk9MVEFHRSk7CgoJcmV0dXJuIDA7Cn0KCnN0YXRpYyBpbnQgbmNwNjMzNWRfc2V0X3ZvbChpbnQgbWFzdGVyX2lkLCBpbnQgdm9sdF9zZWwsIGludCB2b2wpCnsKICAgIGludCB0YXJnZXQgPSB2b2w7CiAgICB1bnNpZ25lZCBjaGFyIGRhdGEsZGF0YV9yZWFkID0gMDsKICAgIHVuc2lnbmVkIGludCBidWNrX3JlZzA7CiAgICBjb25zdCBjaGFyIHNsYXZlQWRkciA9IDB4MUM7CiAgICB1bnNpZ25lZCBjaGFyIGJ1ZmZbMl07CiAgICBpbnQgcmV0ID0gMDsKCiAgICBpZiAodm9sdF9zZWwgPT0gMCl7CiAgICAgICAgYnVja19yZWcwID0gMHgxMTsKICAgIH0gZWxzZSB7CiAgICAgICAgbGdwbF9wcmludGYoIkRvbid0IHN1cHBvcnQgQlVDSzJcbiIpOwogICAgICAgIHJldHVybiAwOwogICAgfQoKICAgIHJldCA9IHBtaWNfdm9sdDJkYXRhKHRhcmdldCwgJmRhdGEpOwoKICAgIGlmIChyZXQgPT0gMCkgewogICAgICAgIGRhdGEgPSAweDgwIHwgZGF0YTsKCiAgICAgICAgYnVmZlswXSA9ICh1bnNpZ25lZCBjaGFyKWJ1Y2tfcmVnMDsKICAgICAgICBidWZmWzFdID0gKHVuc2lnbmVkIGNoYXIpZGF0YTsKICAgICAgICBpMmNfbWFzdGVyX2luaXQobWFzdGVyX2lkLCAxMDAsIDApOwogICAgICAgIC8vIHdyaXRlCiAgICAgICAgcmV0ID0gaTJjX21hc3Rlcl93cml0ZV9hbmRfcmVhZChtYXN0ZXJfaWQsIHNsYXZlQWRkciwgYnVmZiwgMiwgKHVuc2lnbmVkIGNoYXIqKTAsIDApOwogICAgICAgIGlmIChyZXQpIHsKICAgICAgICAgICAgICAgIGxncGxfcHJpbnRmKCJQTUlDIGkyYyB3cml0ZSBmYWlsICFcbiIpOwogICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CgogICAgICAgIC8vIHJlYWQKICAgICAgICBidWZmWzBdID0gKHVuc2lnbmVkIGNoYXIpYnVja19yZWcwOwogICAgICAgIHJldCA9IGkyY19tYXN0ZXJfd3JpdGVfYW5kX3JlYWQobWFzdGVyX2lkLCBzbGF2ZUFkZHIsIGJ1ZmYsIDEsICZkYXRhX3JlYWQsIDEpOwogICAgICAgIGlmIChyZXQpIHsKICAgICAgICAgICAgICAgIGxncGxfcHJpbnRmKCJQTUlDIGkyYyByZWFkIGZhaWwgIVxuIik7CiAgICAgICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KCiAgICAgICAgaWYgKGRhdGFfcmVhZCAhPSBkYXRhKSB7CiAgICAgICAgICAgICAgICBsZ3BsX3ByaW50ZigiUE1JQyBuY3A2MzM1OiByZWFkOjB4JTAyeCAhPSB3cml0ZToweCUwMnhcbiIsIGRhdGEsIGRhdGFfcmVhZCk7CiAgICAgICAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgfQoKICAgICAgICBsZ3BsX3ByaW50Zigic2V0IHRvICVkIHV2XG4iLCB0YXJnZXQpOwogICAgICAgIGRlbGF5X21zKDEpOwogICAgfQoKICAgIHJldHVybiByZXQ7Cn0KCnN0YXRpYyBpbnQgbmNwNjMzNWRfZ2V0X3ZvbChpbnQgbWFzdGVyX2lkLCBpbnQgdm9sdF9zZWwpCnsKCXVuc2lnbmVkIGludCByZWFkID0gMHhmZjsKCXVuc2lnbmVkIGludCBidWNrX3JlZzsKCWNvbnN0IGNoYXIgc2xhdmVBZGRyID0gMHgxQzsKCWludCByZXQ7CglpbnQgdm9sdCA9IDA7CgoJaWYgKHZvbHRfc2VsID09IDApewoJYnVja19yZWcgPSAweDExOwoJfSBlbHNlIHsKCQlsZ3BsX3ByaW50ZigiRG9uJ3Qgc3VwcG9ydCBCVUNLMlxuIik7CgkJcmV0dXJuIC0xOwoJfQoKCWkyY19tYXN0ZXJfaW5pdChtYXN0ZXJfaWQsIDEwMCwgMCk7ICAvL2ludCBpZCwgaW50IHNwZWVkLCBpbnQgYl8xMGJpdF9hZGRyCglyZXQgPSBpMmNfbWFzdGVyX3dyaXRlX2FuZF9yZWFkKG1hc3Rlcl9pZCwgc2xhdmVBZGRyLCAodW5zaWduZWQgY2hhciopJmJ1Y2tfcmVnLCAxLCAodW5zaWduZWQgY2hhciopJnJlYWQsIDEpOwoJaWYgKHJldCAhPSAwKQoJewoJCWxncGxfcHJpbnRmKCIgaTJjIHJlYWQgZmFpbFxuIik7CgkJcmV0dXJuIC1yZXQ7Cgl9CglsZ3BsX3ByaW50ZigiXG5SRUdfVlNFTDAgPSAweCV4IFxuIiwgcmVhZCk7CgoJcmVhZCA9IHJlYWQgJiAweDdGOwoKCWlmKDAgIT0gcG1pY19kYXRhMnZvbHQoJnZvbHQgLCByZWFkKSkgewoJCXJldHVybiAtcmV0OwoJfQoKCXJldHVybiB2b2x0Owp9CgpzdGF0aWMgaW50IGkyY19nZXRfY3B1X3ZvbHQodm9pZCkKewoJaW50IHZvbHQgPSBuY3A2MzM1ZF9nZXRfdm9sKFZPVVRfQ1BVX0lELCBTTEFWRV9BRERSKTsKCglpZih2b2x0IDwgMCkKCQlyZXR1cm4gMDsKCglyZXR1cm4gdm9sdDsKfQoKc3RhdGljIGludCBpMmNfZ2V0X2NvcmVfdm9sdCh2b2lkKQp7CglpbnQgdm9sdCA9IG5jcDYzMzVkX2dldF92b2woVk9VVF9DT1JFX0lELCBTTEFWRV9BRERSKTsKCglpZih2b2x0IDwgMCkKCQlyZXR1cm4gMDsKCglyZXR1cm4gdm9sdDsKfQoKc3RhdGljIGludCBpMmNfc2V0X3ZvbHQoaW50IG1hc3Rlcl9pZCwgaW50IGZyb20sIGludCB0bykKewoJaW50IHZvbHQgPSBmcm9tOwoKCXdoaWxlICh2b2x0ICE9IHRvKXsKCQlpZiAodm9sdCA+IHRvKXsKCQkJdm9sdCAtPSBNSU5JTUFMX1ZPTF9TVEVQX05DUDYzMzVEOwoJCQlpZiAodm9sdCA8IHRvKQoJCQkJdm9sdCA9IHRvOwoJCX1lbHNlewoJCQl2b2x0ICs9IE1JTklNQUxfVk9MX1NURVBfTkNQNjMzNUQ7CgkJCWlmICh2b2x0ID4gdG8pCgkJCQl2b2x0ID0gdG87CgkJfQoKCQlpZigwICE9IG5jcDYzMzVkX3NldF92b2wobWFzdGVyX2lkLCBTTEFWRV9BRERSLCB2b2x0KSkKCQkJcmV0dXJuIDE7CgkJLy91ZGVsYXkoNTApOyAJLy9GSVhNRTogMW1zIGRlbGF5ZWQgaW4gYWJvdmUgZnVuY3Rpb24KCX0KCglyZXR1cm4gMDsKfQoKc3RhdGljIGludCBpMmNfc2V0X3ZjcHVfdm9sdChpbnQgZnJvbSwgaW50IHRvKQp7CglyZXR1cm4gaTJjX3NldF92b2x0KFZPVVRfQ1BVX0lELCBmcm9tICx0byk7Cn0KCnN0YXRpYyBpbnQgaTJjX3NldF92Y29yZV92b2x0KGludCBmcm9tLCBpbnQgdG8pCnsKCXJldHVybiBpMmNfc2V0X3ZvbHQoVk9VVF9DT1JFX0lELCBmcm9tICx0byk7Cn0KCgpjb25zdCBkdmZzX29wc190IG5jcDYzMzVkX29wcyA9IHsKCS5nZXRfdmNwdV92b2x0ID0gaTJjX2dldF9jcHVfdm9sdCwKCS5nZXRfdmNvcmVfdm9sdCA9IGkyY19nZXRfY29yZV92b2x0LAoJLnNldF92Y3B1X3ZvbHQgPSBpMmNfc2V0X3ZjcHVfdm9sdCwKCS5zZXRfdmNvcmVfdm9sdCA9aTJjX3NldF92Y29yZV92b2x0Cn07Cg==