LyoKICogRE9TIFZpcnR1YWwgTWFjaGluZQogKgogKiBDb3B5cmlnaHQgMTk5OCBPdmUgS+V2ZW4KICoKICogVGhpcyBjb2RlIGhhc24ndCBiZWVuIGNvbXBsZXRlbHkgY2xlYW5lZCB1cCB5ZXQuCiAqLwoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8ZXJybm8uaD4KI2luY2x1ZGUgPGZjbnRsLmg+CiNpbmNsdWRlIDxzaWduYWwuaD4KI2luY2x1ZGUgPHVuaXN0ZC5oPgojaW5jbHVkZSA8c3lzL3RpbWUuaD4KI2luY2x1ZGUgPHN5cy90eXBlcy5oPgojaW5jbHVkZSA8c3lzL3N0YXQuaD4KI2luY2x1ZGUgIndpbmRvd3MuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbm50LmgiCiNpbmNsdWRlICJzaWdfY29udGV4dC5oIgojaW5jbHVkZSAibXNkb3MuaCIKI2luY2x1ZGUgIm1pc2NlbXUuaCIKI2luY2x1ZGUgImRlYnVnZ2VyLmgiCiNpbmNsdWRlICJkZWJ1Zy5oIgojaW5jbHVkZSAibW9kdWxlLmgiCiNpbmNsdWRlICJ0YXNrLmgiCiNpbmNsdWRlICJsZHQuaCIKI2luY2x1ZGUgImRvc2V4ZS5oIgoKdm9pZCAoKmN0eF9kZWJ1Z19jYWxsKShpbnQgc2lnLENPTlRFWFQqY3R4KT1OVUxMOwpCT09MMzIgKCppbnN0cl9lbXVfY2FsbCkoU0lHQ09OVEVYVCpjdHgpPU5VTEw7CgojaWZkZWYgTVpfU1VQUE9SVEVECgojaW5jbHVkZSA8c3lzL21tYW4uaD4KI2luY2x1ZGUgPHN5cy92bTg2Lmg+CgpzdGF0aWMgdm9pZCBET1NWTV9EdW1wKCBMUERPU1RBU0sgbHBEb3NUYXNrLCBpbnQgZm4sCiAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCB2bTg2cGx1c19zdHJ1Y3QqVk04NiApCnsKIHVuc2lnbmVkIGlvZnM7CiBCWVRFKmluc3Q7CiBpbnQgeDsKCiBzd2l0Y2ggKFZNODZfVFlQRShmbikpIHsKICBjYXNlIFZNODZfU0lHTkFMOgogICBwcmludGYoIlRyYXBwZWQgc2lnbmFsXG4iKTsgYnJlYWs7CiAgY2FzZSBWTTg2X1VOS05PV046CiAgIHByaW50ZigiVHJhcHBlZCB1bmhhbmRsZWQgR1BGXG4iKTsgYnJlYWs7CiAgY2FzZSBWTTg2X0lOVHg6CiAgIHByaW50ZigiVHJhcHBlZCBJTlQgJTAyeFxuIixWTTg2X0FSRyhmbikpOyBicmVhazsKICBjYXNlIFZNODZfU1RJOgogICBwcmludGYoIlRyYXBwZWQgU1RJXG4iKTsgYnJlYWs7CiAgY2FzZSBWTTg2X1BJQ1JFVFVSTjoKICAgcHJpbnRmKCJUcmFwcGVkIGR1ZSB0byBwZW5kaW5nIFBJQyByZXF1ZXN0XG4iKTsgYnJlYWs7CiAgY2FzZSBWTTg2X1RSQVA6CiAgIHByaW50ZigiVHJhcHBlZCBkZWJ1ZyByZXF1ZXN0XG4iKTsgYnJlYWs7CiAgZGVmYXVsdDoKICAgcHJpbnRmKCJUcmFwcGVkIHVua25vd24gVk04NiB0eXBlICVkIGFyZyAlZFxuIixWTTg2X1RZUEUoZm4pLFZNODZfQVJHKGZuKSk7IGJyZWFrOwogfQojZGVmaW5lIFJFR1MgVk04Ni0+cmVncwogZnByaW50ZihzdGRlcnIsIkFYPSUwNGxYIENYPSUwNGxYIERYPSUwNGxYIEJYPSUwNGxYXG4iLFJFR1MuZWF4LFJFR1MuZWN4LFJFR1MuZWR4LFJFR1MuZWJ4KTsKIGZwcmludGYoc3RkZXJyLCJTST0lMDRsWCBEST0lMDRsWCBTUD0lMDRsWCBCUD0lMDRsWFxuIixSRUdTLmVzaSxSRUdTLmVkaSxSRUdTLmVzcCxSRUdTLmVicCk7CiBmcHJpbnRmKHN0ZGVyciwiQ1M9JTA0WCBEUz0lMDRYIEVTPSUwNFggU1M9JTA0WFxuIixSRUdTLmNzLFJFR1MuZHMsUkVHUy5lcyxSRUdTLnNzKTsKIGZwcmludGYoc3RkZXJyLCJJUD0lMDRsWCBFRkxBR1M9JTA4bFhcbiIsUkVHUy5laXAsUkVHUy5lZmxhZ3MpOwoKIGlvZnM9KChEV09SRClSRUdTLmNzPDw0KStSRUdTLmVpcDsKI3VuZGVmIFJFR1MKIGluc3Q9KEJZVEUqKWxwRG9zVGFzay0+aW1nK2lvZnM7CiBwcmludGYoIk9wY29kZXM6Iik7CiBmb3IgKHg9MDsgeDw4OyB4KyspIHByaW50ZigiICUwMngiLGluc3RbeF0pOwogcHJpbnRmKCJcbiIpOwp9CgpzdGF0aWMgaW50IERPU1ZNX0ludCggaW50IHZlY3QsIFBDT05URVhUIGNvbnRleHQsIExQRE9TVEFTSyBscERvc1Rhc2sgKQp7CiBpZiAodmVjdD09MHgzMSkgewogIGlmIChDU19yZWcoY29udGV4dCk9PWxwRG9zVGFzay0+ZHBtaV9zZWwpIHsKICAgaWYgKElQX3JlZyhjb250ZXh0KT49bHBEb3NUYXNrLT53cmFwX29mcykgewogICAgLyogZXhpdCBmcm9tIHJlYWwtbW9kZSB3cmFwcGVyICovCiAgICByZXR1cm4gLTE7CiAgIH0KICB9CiAgLyogd2UgY291bGQgcHJvYmFibHkgbW92ZSBzb21lIG90aGVyIGRvZGd5IHN0dWZmIGhlcmUgdG9vIGZyb20gZHBtaS5jICovCiB9CiBJTlRfUmVhbE1vZGVJbnRlcnJ1cHQodmVjdCxjb250ZXh0KTsKIHJldHVybiAwOwp9CgojZGVmaW5lIENWIENQKGVheCxFQVgpOyBDUChlY3gsRUNYKTsgQ1AoZWR4LEVEWCk7IENQKGVieCxFQlgpOyBcCiAgICAgICAgICAgQ1AoZXNpLEVTSSk7IENQKGVkaSxFREkpOyBDUChlc3AsRVNQKTsgQ1AoZWJwLEVCUCk7IFwKICAgICAgICAgICBDUChjcyxDUyk7IENQKGRzLERTKTsgQ1AoZXMsRVMpOyBcCiAgICAgICAgICAgQ1Aoc3MsU1MpOyBDUChmcyxGUyk7IENQKGdzLEdTKTsgXAogICAgICAgICAgIENQKGVpcCxFSVApOyBDUChlZmxhZ3MsRUZMKQoKc3RhdGljIGludCBET1NWTV9Qcm9jZXNzKCBMUERPU1RBU0sgbHBEb3NUYXNrLCBpbnQgZm4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHZtODZwbHVzX3N0cnVjdCpWTTg2ICkKewogU0lHQ09OVEVYVCBzaWdjb250ZXh0OwogQ09OVEVYVCBjb250ZXh0OwogaW50IHJldD0wOwoKIGlmIChWTTg2X1RZUEUoZm4pPT1WTTg2X1VOS05PV04pIHsKICAvKiBJTlNUUl9FbXVsYXRlSW5zdHJ1Y3Rpb24gbmVlZHMgYSBTSUdDT05URVhULCBub3QgYSBDT05URVhULi4uICovCiNkZWZpbmUgQ1AoeCx5KSB5IyNfc2lnKCZzaWdjb250ZXh0KSA9IFZNODYtPnJlZ3MueAogIENWOwojdW5kZWYgQ1AKICBpZiAoaW5zdHJfZW11X2NhbGwpIHJldD1pbnN0cl9lbXVfY2FsbCgmc2lnY29udGV4dCk7CiNkZWZpbmUgQ1AoeCx5KSBWTTg2LT5yZWdzLnggPSB5IyNfc2lnKCZzaWdjb250ZXh0KQogIENWOwojdW5kZWYgQ1AKICBpZiAocmV0KSByZXR1cm4gMDsKICByZXQ9MDsKIH0KI2RlZmluZSBDUCh4LHkpIHkjI19yZWcoJmNvbnRleHQpID0gVk04Ni0+cmVncy54CiBDVjsKI3VuZGVmIENQCiAodm9pZCopVjg2QkFTRSgmY29udGV4dCk9bHBEb3NUYXNrLT5pbWc7Cgogc3dpdGNoIChWTTg2X1RZUEUoZm4pKSB7CiAgY2FzZSBWTTg2X1NJR05BTDoKICAgRE9TVk1fRHVtcChscERvc1Rhc2ssZm4sVk04Nik7CiAgIHJldD0tMTsgYnJlYWs7CiAgY2FzZSBWTTg2X1VOS05PV046IC8qIHVuaGFuZGxlZCBHUEYgKi8KICAgRE9TVk1fRHVtcChscERvc1Rhc2ssZm4sVk04Nik7CiAgIGlmIChjdHhfZGVidWdfY2FsbCkgY3R4X2RlYnVnX2NhbGwoU0lHU0VHViwmY29udGV4dCk7IGVsc2UgcmV0PS0xOwogICBicmVhazsKICBjYXNlIFZNODZfSU5UeDoKICAgVFJBQ0UoaW50LCJET1MgRVhFIGNhbGxzIElOVCAlMDJ4IHdpdGggQVg9JTA0bHhcbiIsVk04Nl9BUkcoZm4pLGNvbnRleHQuRWF4KTsKICAgcmV0PURPU1ZNX0ludChWTTg2X0FSRyhmbiksJmNvbnRleHQsbHBEb3NUYXNrKTsgYnJlYWs7CiAgY2FzZSBWTTg2X1NUSToKICAgYnJlYWs7CiAgY2FzZSBWTTg2X1BJQ1JFVFVSTjoKICAgcHJpbnRmKCJUcmFwcGVkIGR1ZSB0byBwZW5kaW5nIFBJQyByZXF1ZXN0XG4iKTsgYnJlYWs7CiAgY2FzZSBWTTg2X1RSQVA6CiAgIGlmIChjdHhfZGVidWdfY2FsbCkgY3R4X2RlYnVnX2NhbGwoU0lHVFJBUCwmY29udGV4dCk7CiAgIGJyZWFrOwogIGRlZmF1bHQ6CiAgIERPU1ZNX0R1bXAobHBEb3NUYXNrLGZuLFZNODYpOwogICByZXQ9LTE7CiB9CgojZGVmaW5lIENQKHgseSkgVk04Ni0+cmVncy54ID0geSMjX3JlZygmY29udGV4dCkKIENWOwojdW5kZWYgQ1AKIHJldHVybiByZXQ7Cn0KCmludCBET1NWTV9FbnRlciggUENPTlRFWFQgY29udGV4dCApCnsKIFREQiAqcFRhc2sgPSAoVERCICopR2xvYmFsTG9jazE2KCBHZXRDdXJyZW50VGFzaygpICk7CiBORV9NT0RVTEUgKnBNb2R1bGUgPSBORV9HZXRQdHIoIHBUYXNrLT5oTW9kdWxlICk7CiBMUERPU1RBU0sgbHBEb3NUYXNrOwogc3RydWN0IHZtODZwbHVzX3N0cnVjdCBWTTg2OwogaW50IHN0YXQsbGVuOwogZmRfc2V0IHJlYWRmZHMsZXhjZXB0ZmRzOwoKIEdsb2JhbFVubG9jazE2KCBHZXRDdXJyZW50VGFzaygpICk7CiBpZiAoIXBNb2R1bGUpIHsKICBFUlIobW9kdWxlLCJObyB0YXNrIGlzIGN1cnJlbnRseSBhY3RpdmUhXG4iKTsKICByZXR1cm4gLTE7CiB9CiBpZiAoIXBNb2R1bGUtPmxwRG9zVGFzaykgewogIC8qIG5vIFZNODYgKGRvc21vZCkgdGFzayBpcyBjdXJyZW50bHkgcnVubmluZywgc3RhcnQgb25lICovCiAgaWYgKChscERvc1Rhc2sgPSBjYWxsb2MoMSwgc2l6ZW9mKERPU1RBU0spKSkgPT0gTlVMTCkKICAgIHJldHVybiAwOwogIGxwRG9zVGFzay0+aE1vZHVsZT1wTW9kdWxlLT5zZWxmOwogIHN0YXQ9TVpfSW5pdE1lbW9yeShscERvc1Rhc2sscE1vZHVsZSk7CiAgaWYgKHN0YXQ+PTMyKSBzdGF0PU1aX0luaXRUYXNrKGxwRG9zVGFzayk7CiAgaWYgKHN0YXQ8MzIpIHsKICAgZnJlZShscERvc1Rhc2spOwogICByZXR1cm4gLTE7CiAgfQogIHBNb2R1bGUtPmxwRG9zVGFzayA9IGxwRG9zVGFzazsKICBwTW9kdWxlLT5kb3NfaW1hZ2UgPSBscERvc1Rhc2stPmltZzsKICAvKiBOb3RlOiB3ZSdyZSBsZWF2aW5nIGl0IHJ1bm5pbmcgYWZ0ZXIgdGhpcywgaW4gY2FzZSB3ZSBuZWVkIGl0IGFnYWluLAogICAgIGFzIHRoaXMgbWluaW1pemVzIHRoZSBvdmVyaGVhZCBvZiBzdGFydGluZyBpdCB1cCBldmVyeSB0aW1lLi4uCiAgICAgaXQgd2lsbCBiZSBraWxsZWQgYXV0b21hdGljYWxseSB3aGVuIHRoZSBjdXJyZW50IHRhc2sgdGVybWluYXRlcyAqLwogfSBlbHNlIGxwRG9zVGFzaz1wTW9kdWxlLT5scERvc1Rhc2s7CgogaWYgKGNvbnRleHQpIHsKI2RlZmluZSBDUCh4LHkpIFZNODYucmVncy54ID0geSMjX3JlZyhjb250ZXh0KQogIENWOwojdW5kZWYgQ1AKIH0gZWxzZSB7Ci8qIGluaXRpYWwgc2V0dXAgKi8KICBtZW1zZXQoJlZNODYsMCxzaXplb2YoVk04NikpOwogIFZNODYucmVncy5jcz1scERvc1Rhc2stPmluaXRfY3M7CiAgVk04Ni5yZWdzLmVpcD1scERvc1Rhc2stPmluaXRfaXA7CiAgVk04Ni5yZWdzLnNzPWxwRG9zVGFzay0+aW5pdF9zczsKICBWTTg2LnJlZ3MuZXNwPWxwRG9zVGFzay0+aW5pdF9zcDsKICBWTTg2LnJlZ3MuZHM9bHBEb3NUYXNrLT5wc3Bfc2VnOwogIFZNODYucmVncy5lcz1scERvc1Rhc2stPnBzcF9zZWc7CiAgLyogaG1tLCB3aGF0IGVsc2UgZG8gd2UgbmVlZD8gKi8KIH0KCiAvKiBtYWluIGV4Y2hhbmdlIGxvb3AgKi8KIGRvIHsKICBzdGF0ID0gVk04Nl9FTlRFUjsKICAvKiB0cmFuc21pdCBWTTg2IHN0cnVjdHVyZSB0byBkb3Ntb2QgdGFzayAqLwogIGlmICh3cml0ZShscERvc1Rhc2stPndyaXRlX3BpcGUsJnN0YXQsc2l6ZW9mKHN0YXQpKSE9c2l6ZW9mKHN0YXQpKSB7CiAgIEVSUihtb2R1bGUsImRvc21vZCBzeW5jIGxvc3QsIGVycm5vPSVkXG4iLGVycm5vKTsKICAgcmV0dXJuIC0xOwogIH0KICBpZiAod3JpdGUobHBEb3NUYXNrLT53cml0ZV9waXBlLCZWTTg2LHNpemVvZihWTTg2KSkhPXNpemVvZihWTTg2KSkgewogICBFUlIobW9kdWxlLCJkb3Ntb2Qgc3luYyBsb3N0LCBlcnJubz0lZFxuIixlcnJubyk7CiAgIHJldHVybiAtMTsKICB9CiAgLyogd2FpdCBmb3IgcmVzcG9uc2UsIHdpdGggYXN5bmMgZXZlbnRzIGVuYWJsZWQgKi8KICBGRF9aRVJPKCZyZWFkZmRzKTsKICBGRF9aRVJPKCZleGNlcHRmZHMpOwogIFNJR05BTF9NYXNrQXN5bmNFdmVudHMoRkFMU0UpOwogIGRvIHsKICAgRkRfU0VUKGxwRG9zVGFzay0+cmVhZF9waXBlLCZyZWFkZmRzKTsKICAgRkRfU0VUKGxwRG9zVGFzay0+cmVhZF9waXBlLCZleGNlcHRmZHMpOwogICBzZWxlY3QobHBEb3NUYXNrLT5yZWFkX3BpcGUrMSwmcmVhZGZkcyxOVUxMLCZleGNlcHRmZHMsTlVMTCk7CiAgfSB3aGlsZSAoIShGRF9JU1NFVChscERvc1Rhc2stPnJlYWRfcGlwZSwmcmVhZGZkcyl8fAogICAgICAgICAgICAgRkRfSVNTRVQobHBEb3NUYXNrLT5yZWFkX3BpcGUsJmV4Y2VwdGZkcykpKTsKICBTSUdOQUxfTWFza0FzeW5jRXZlbnRzKFRSVUUpOwogIC8qIHJlYWQgcmVzcG9uc2UgKHdpdGggYXN5bmMgZXZlbnRzIGRpc2FibGVkIHRvIGF2b2lkIHNvbWUgc3RyYW5nZSBwcm9ibGVtcykgKi8KICBkbyB7CiAgIGlmICgobGVuPXJlYWQobHBEb3NUYXNrLT5yZWFkX3BpcGUsJnN0YXQsc2l6ZW9mKHN0YXQpKSkhPXNpemVvZihzdGF0KSkgewogICAgaWYgKCgoZXJybm89PUVJTlRSKXx8KGVycm5vPT1FQUdBSU4pKSYmKGxlbjw9MCkpIHsKICAgICBXQVJOKG1vZHVsZSwicmVyZWFkaW5nIGRvc21vZCByZXR1cm4gY29kZSBkdWUgdG8gZXJybm89JWQsIHJlc3VsdD0lZFxuIixlcnJubyxsZW4pOwogICAgIGNvbnRpbnVlOwogICAgfQogICAgRVJSKG1vZHVsZSwiZG9zbW9kIHN5bmMgbG9zdCByZWFkaW5nIHJldHVybiBjb2RlLCBlcnJubz0lZCwgcmVzdWx0PSVkXG4iLGVycm5vLGxlbik7CiAgICByZXR1cm4gLTE7CiAgIH0KICB9IHdoaWxlICgwKTsKICBUUkFDRShtb2R1bGUsImRvc21vZCByZXR1cm4gY29kZT0lZFxuIixzdGF0KTsKICBkbyB7CiAgIGlmICgobGVuPXJlYWQobHBEb3NUYXNrLT5yZWFkX3BpcGUsJlZNODYsc2l6ZW9mKFZNODYpKSkhPXNpemVvZihWTTg2KSkgewogICAgaWYgKCgoZXJybm89PUVJTlRSKXx8KGVycm5vPT1FQUdBSU4pKSYmKGxlbjw9MCkpIHsKICAgICBXQVJOKG1vZHVsZSwicmVyZWFkaW5nIGRvc21vZCBWTTg2IHN0cnVjdHVyZSBkdWUgdG8gZXJybm89JWQsIHJlc3VsdD0lZFxuIixlcnJubyxsZW4pOwogICAgIGNvbnRpbnVlOwogICAgfQogICAgRVJSKG1vZHVsZSwiZG9zbW9kIHN5bmMgbG9zdCByZWFkaW5nIFZNODYgc3RydWN0dXJlLCBlcnJubz0lZCwgcmVzdWx0PSVkXG4iLGVycm5vLGxlbik7CiAgICByZXR1cm4gLTE7CiAgIH0KICB9IHdoaWxlICgwKTsKICAvKiBnb3QgcmVzcG9uc2UgKi8KIH0gd2hpbGUgKERPU1ZNX1Byb2Nlc3MobHBEb3NUYXNrLHN0YXQsJlZNODYpPj0wKTsKCiBpZiAoY29udGV4dCkgewojZGVmaW5lIENQKHgseSkgeSMjX3JlZyhjb250ZXh0KSA9IFZNODYucmVncy54CiAgQ1Y7CiN1bmRlZiBDUAogfQogcmV0dXJuIDA7Cn0KCnZvaWQgTVpfVGljayggV09SRCBoYW5kbGUgKQp7CiAvKiBmaW5kIHRoZSBET1MgdGFzayB0aGF0IGhhcyB0aGUgcmlnaHQgc3lzdGVtX3RpbWVyIGhhbmRsZS4uLiAqLwogLyogc2hvdWxkIHVzdWFsbHkgYmUgdGhlIGN1cnJlbnQsIHNvIGxldCdzIGp1c3QgYmUgbGF6eS4uLiAqLwogVERCICpwVGFzayA9IChUREIqKUdsb2JhbExvY2sxNiggR2V0Q3VycmVudFRhc2soKSApOwogTkVfTU9EVUxFICpwTW9kdWxlID0gcFRhc2sgPyBORV9HZXRQdHIoIHBUYXNrLT5oTW9kdWxlICkgOiBOVUxMOwogTFBET1NUQVNLIGxwRG9zVGFzayA9IHBNb2R1bGUgPyBwTW9kdWxlLT5scERvc1Rhc2sgOiBOVUxMOwoKIEdsb2JhbFVubG9jazE2KCBHZXRDdXJyZW50VGFzaygpICk7CiBpZiAobHBEb3NUYXNrJiYobHBEb3NUYXNrLT5zeXN0ZW1fdGltZXI9PWhhbmRsZSkpIHsKICAvKiBCSU9TIHRpbWVyIHRpY2sgKi8KICAoKigoRFdPUkQqKSgoKEJZVEUqKShscERvc1Rhc2stPmltZykpKzB4NDZjKSkpKys7CiB9Cn0KCiNlbHNlIC8qICFNWl9TVVBQT1JURUQgKi8KCmludCBET1NWTV9FbnRlciggUENPTlRFWFQgY29udGV4dCApCnsKIEVSUihtb2R1bGUsIkRPUyByZWFsbW9kZSBub3Qgc3VwcG9ydGVkIG9uIHRoaXMgYXJjaGl0ZWN0dXJlIVxuIik7CiByZXR1cm4gLTE7Cn0KCnZvaWQgTVpfVGljayggV09SRCBoYW5kbGUgKSB7fQoKI2VuZGlmCg==