LyoKICogVkdBIGhhcmR3YXJlIGVtdWxhdGlvbgogKiAKICogQ29weXJpZ2h0IDE5OTggT3ZlIEvldmVuICh3aXRoIHNvbWUgaGVscCBmcm9tIE1hcmN1cyBNZWlzc25lcikKICoKICovCgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlICJ3aW5kb3dzLmgiCiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJtaXNjZW11LmgiCiNpbmNsdWRlICJ2Z2EuaCIKI2luY2x1ZGUgImNvbXBvYmouaCIKI2luY2x1ZGUgImludGVyZmFjZXMuaCIKI2luY2x1ZGUgImRkcmF3LmgiCiNpbmNsdWRlICJkZWJ1Zy5oIgoKc3RhdGljIElEaXJlY3REcmF3ICpscGRkcmF3ID0gTlVMTDsKc3RhdGljIElEaXJlY3REcmF3U3VyZmFjZSAqbHBkZHN1cmY7CnN0YXRpYyBJRGlyZWN0RHJhd1BhbGV0dGUgKmxwZGRwYWw7CnN0YXRpYyBERFNVUkZBQ0VERVNDIHNkZXNjOwpzdGF0aWMgV09SRCBwb2xsX3RpbWVyOwpzdGF0aWMgQ1JJVElDQUxfU0VDVElPTiB2Z2FfY3JpdDsKc3RhdGljIGludCB2Z2FfcG9sbGluZyx2Z2FfcmVmcmVzaDsKCmludCBWR0FfU2V0TW9kZSh1bnNpZ25lZCBYcmVzLHVuc2lnbmVkIFlyZXMsdW5zaWduZWQgRGVwdGgpCnsKICAgIGlmIChscGRkcmF3KSBWR0FfRXhpdCgpOwogICAgaWYgKCFscGRkcmF3KSB7CiAgICAgICAgRGlyZWN0RHJhd0NyZWF0ZShOVUxMLCZscGRkcmF3LE5VTEwpOwogICAgICAgIGlmICghbHBkZHJhdykgewogICAgICAgICAgICBFUlIoZGRyYXcsIkRpcmVjdERyYXcgaXMgbm90IGF2YWlsYWJsZVxuIik7CiAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgIH0KICAgICAgICBpZiAobHBkZHJhdy0+bHB2dGJsLT5mblNldERpc3BsYXlNb2RlKGxwZGRyYXcsWHJlcyxZcmVzLERlcHRoKSkgewogICAgICAgICAgICBFUlIoZGRyYXcsIkRpcmVjdERyYXcgZG9lcyBub3Qgc3VwcG9ydCByZXF1ZXN0ZWQgZGlzcGxheSBtb2RlXG4iKTsKICAgICAgICAgICAgbHBkZHJhdy0+bHB2dGJsLT5mblJlbGVhc2UobHBkZHJhdyk7CiAgICAgICAgICAgIGxwZGRyYXc9TlVMTDsKICAgICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfQogICAgICAgIGxwZGRyYXctPmxwdnRibC0+Zm5DcmVhdGVQYWxldHRlKGxwZGRyYXcsMCxOVUxMLCZscGRkcGFsLE5VTEwpOwogICAgICAgIG1lbXNldCgmc2Rlc2MsMCxzaXplb2Yoc2Rlc2MpKTsKICAgICAgICBzZGVzYy5kd1NpemU9c2l6ZW9mKHNkZXNjKTsKICAgICAgICBpZiAobHBkZHJhdy0+bHB2dGJsLT5mbkNyZWF0ZVN1cmZhY2UobHBkZHJhdywmc2Rlc2MsJmxwZGRzdXJmLE5VTEwpfHwoIWxwZGRzdXJmKSkgewogICAgICAgICAgICBFUlIoZGRyYXcsIkRpcmVjdERyYXcgc3VyZmFjZSBpcyBub3QgYXZhaWxhYmxlXG4iKTsKICAgICAgICAgICAgbHBkZHJhdy0+bHB2dGJsLT5mblJlbGVhc2UobHBkZHJhdyk7CiAgICAgICAgICAgIGxwZGRyYXc9TlVMTDsKICAgICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfQogICAgICAgIHZnYV9yZWZyZXNoPTA7CiAgICAgICAgSW5pdGlhbGl6ZUNyaXRpY2FsU2VjdGlvbigmdmdhX2NyaXQpOwogICAgICAgIC8qIHBvbGwgZXZlcnkgMjBtcyAoNTBmcHMgc2hvdWxkIHByb3ZpZGUgYWRlcXVhdGUgcmVzcG9uc2l2ZW5lc3MpICovCiAgICAgICAgcG9sbF90aW1lciA9IENyZWF0ZVN5c3RlbVRpbWVyKCAyMCwgKEZBUlBST0MxNilWR0FfUG9sbCApOwogICAgfQogICAgcmV0dXJuIDA7Cn0KCmludCBWR0FfR2V0TW9kZSh1bnNpZ25lZCpIZWlnaHQsdW5zaWduZWQqV2lkdGgsdW5zaWduZWQqRGVwdGgpCnsKICAgIGlmICghbHBkZHJhdykgcmV0dXJuIDE7CiAgICBpZiAoIWxwZGRzdXJmKSByZXR1cm4gMTsKICAgIGlmIChIZWlnaHQpICpIZWlnaHQ9c2Rlc2MuZHdIZWlnaHQ7CiAgICBpZiAoV2lkdGgpICpXaWR0aD1zZGVzYy5kd1dpZHRoOwogICAgaWYgKERlcHRoKSAqRGVwdGg9c2Rlc2MuZGRwZlBpeGVsRm9ybWF0LnguZHdSR0JCaXRDb3VudDsKICAgIHJldHVybiAwOwp9Cgp2b2lkIFZHQV9FeGl0KHZvaWQpCnsKICAgIGlmIChscGRkcmF3KSB7CiAgICAgICAgU1lTVEVNX0tpbGxTeXN0ZW1UaW1lcihwb2xsX3RpbWVyKTsKICAgICAgICBEZWxldGVDcml0aWNhbFNlY3Rpb24oJnZnYV9jcml0KTsKICAgICAgICBscGRkc3VyZi0+bHB2dGJsLT5mblJlbGVhc2UobHBkZHN1cmYpOwogICAgICAgIGxwZGRzdXJmPU5VTEw7CiAgICAgICAgbHBkZHJhdy0+bHB2dGJsLT5mblJlbGVhc2UobHBkZHJhdyk7CiAgICAgICAgbHBkZHJhdz1OVUxMOwogICAgfQp9Cgp2b2lkIFZHQV9TZXRQYWxldHRlKFBBTEVUVEVFTlRSWSpwYWwsaW50IHN0YXJ0LGludCBsZW4pCnsKICAgIGlmICghbHBkZHJhdykgcmV0dXJuOwogICAgbHBkZHBhbC0+bHB2dGJsLT5mblNldEVudHJpZXMobHBkZHBhbCwwLHN0YXJ0LGxlbixwYWwpOwogICAgbHBkZHN1cmYtPmxwdnRibC0+Zm5TZXRQYWxldHRlKGxwZGRzdXJmLGxwZGRwYWwpOwp9Cgp2b2lkIFZHQV9TZXRRdWFkUGFsZXR0ZShSR0JRVUFEKmNvbG9yLGludCBzdGFydCxpbnQgbGVuKQp7CiAgICBQQUxFVFRFRU5UUlkgcGFsWzI1Nl07CiAgICBpbnQgYzsKCiAgICBpZiAoIWxwZGRyYXcpIHJldHVybjsKICAgIGZvciAoYz0wOyBjPGxlbjsgYysrKSB7CiAgICAgICAgcGFsW2NdLnBlUmVkICA9Y29sb3JbY10ucmdiUmVkOwogICAgICAgIHBhbFtjXS5wZUdyZWVuPWNvbG9yW2NdLnJnYkdyZWVuOwogICAgICAgIHBhbFtjXS5wZUJsdWUgPWNvbG9yW2NdLnJnYkJsdWU7CiAgICAgICAgcGFsW2NdLnBlRmxhZ3M9MDsKICAgIH0KICAgIGxwZGRwYWwtPmxwdnRibC0+Zm5TZXRFbnRyaWVzKGxwZGRwYWwsMCxzdGFydCxsZW4scGFsKTsKICAgIGxwZGRzdXJmLT5scHZ0YmwtPmZuU2V0UGFsZXR0ZShscGRkc3VyZixscGRkcGFsKTsKfQoKTFBTVFIgVkdBX0xvY2sodW5zaWduZWQqUGl0Y2gsdW5zaWduZWQqSGVpZ2h0LHVuc2lnbmVkKldpZHRoLHVuc2lnbmVkKkRlcHRoKQp7CiAgICBpZiAoIWxwZGRyYXcpIHJldHVybiBOVUxMOwogICAgaWYgKCFscGRkc3VyZikgcmV0dXJuIE5VTEw7CiAgICBpZiAobHBkZHN1cmYtPmxwdnRibC0+Zm5Mb2NrKGxwZGRzdXJmLE5VTEwsJnNkZXNjLDAsMCkpIHsKICAgICAgICBFUlIoZGRyYXcsImNvdWxkIG5vdCBsb2NrIHN1cmZhY2UhXG4iKTsKICAgICAgICByZXR1cm4gTlVMTDsKICAgIH0KICAgIGlmIChQaXRjaCkgKlBpdGNoPXNkZXNjLmxQaXRjaDsKICAgIGlmIChIZWlnaHQpICpIZWlnaHQ9c2Rlc2MuZHdIZWlnaHQ7CiAgICBpZiAoV2lkdGgpICpXaWR0aD1zZGVzYy5kd1dpZHRoOwogICAgaWYgKERlcHRoKSAqRGVwdGg9c2Rlc2MuZGRwZlBpeGVsRm9ybWF0LnguZHdSR0JCaXRDb3VudDsKICAgIHJldHVybiBzZGVzYy55LmxwU3VyZmFjZTsKfQoKdm9pZCBWR0FfVW5sb2NrKHZvaWQpCnsKICAgIGxwZGRzdXJmLT5scHZ0YmwtPmZuVW5sb2NrKGxwZGRzdXJmLHNkZXNjLnkubHBTdXJmYWNlKTsKfQoKdm9pZCBWR0FfUG9sbCh2b2lkKQp7CiAgICBjaGFyICpkYXQ7CiAgICB1bnNpZ25lZCBQaXRjaCxIZWlnaHQsV2lkdGg7CiAgICBjaGFyICpzdXJmOwogICAgaW50IFksWDsKCiAgICBFbnRlckNyaXRpY2FsU2VjdGlvbigmdmdhX2NyaXQpOwogICAgaWYgKCF2Z2FfcG9sbGluZykgewogICAgICAgIHZnYV9wb2xsaW5nKys7CiAgICAgICAgTGVhdmVDcml0aWNhbFNlY3Rpb24oJnZnYV9jcml0KTsKICAgICAgICAvKiBGSVhNRTogb3B0aW1pemUgYnkgZG9pbmcgdGhpcyBvbmx5IGlmIHRoZSBkYXRhIGhhcyBhY3R1YWxseSBjaGFuZ2VkCiAgICAgICAgICogICAgICAgIChpbiBhIHdheSBzaW1pbGFyIHRvIERJQlNlY3Rpb24sIHBlcmhhcHMpICovCiAgICAgICAgc3VyZiA9IFZHQV9Mb2NrKCZQaXRjaCwmSGVpZ2h0LCZXaWR0aCxOVUxMKTsKICAgICAgICBpZiAoIXN1cmYpIHJldHVybjsKICAgICAgICBkYXQgPSBET1NNRU1fTWFwRG9zVG9MaW5lYXIoMHhhMDAwMCk7CiAgICAgICAgLyogY29weSBmcm9tIHZpcnR1YWwgVkdBIGZyYW1lIGJ1ZmZlciB0byBEaXJlY3REcmF3IHN1cmZhY2UgKi8KICAgICAgICBmb3IgKFk9MDsgWTxIZWlnaHQ7IFkrKyxzdXJmKz1QaXRjaCxkYXQrPVdpZHRoKSB7CiAgICAgICAgICAgIG1lbWNweShzdXJmLGRhdCxXaWR0aCk7CiAgICAgICAgICAgIGZvciAoWD0wOyBYPFdpZHRoOyBYKyspIGlmIChkYXRbWF0pIFRSQUNFKGRkcmF3LCJkYXRhKCVkKSBhdCAoJWQsJWQpXG4iLGRhdFtYXSxYLFkpOwogICAgICAgIH0KICAgICAgICBWR0FfVW5sb2NrKCk7CiAgICAgICAgdmdhX3JlZnJlc2g9MTsKICAgICAgICBFbnRlckNyaXRpY2FsU2VjdGlvbigmdmdhX2NyaXQpOwogICAgICAgIHZnYV9wb2xsaW5nLS07CiAgICB9CiAgICBMZWF2ZUNyaXRpY2FsU2VjdGlvbigmdmdhX2NyaXQpOwp9CgpzdGF0aWMgQllURSBwYWxyZWcscGFsY250OwpzdGF0aWMgUEFMRVRURUVOVFJZIHBhbGRhdDsKCnZvaWQgVkdBX2lvcG9ydF9vdXQoIFdPUkQgcG9ydCwgQllURSB2YWwgKQp7CiAgICBzd2l0Y2ggKHBvcnQpIHsKICAgICAgICBjYXNlIDB4M2M4OgogICAgICAgICAgICBwYWxyZWc9dmFsOyBwYWxjbnQ9MDsgYnJlYWs7CiAgICAgICAgY2FzZSAweDNjOToKICAgICAgICAgICAgKChCWVRFKikmcGFsZGF0KVtwYWxjbnQrK109dmFsIDw8IDI7CiAgICAgICAgICAgIGlmIChwYWxjbnQ9PTMpIHsKICAgICAgICAgICAgICAgIFZHQV9TZXRQYWxldHRlKCZwYWxkYXQscGFscmVnLDEpOwogICAgICAgICAgICAgICAgcGFscmVnKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICB9Cn0KCkJZVEUgVkdBX2lvcG9ydF9pbiggV09SRCBwb3J0ICkKewogICAgQllURSByZXQ7CgogICAgc3dpdGNoIChwb3J0KSB7CiAgICAgICAgY2FzZSAweDNkYToKICAgICAgICAgICAgLyogc2luY2Ugd2UgZG9uJ3QgKHlldD8pIHNlcnZlIERPUyBWTSByZXF1ZXN0cyB3aGlsZSBWR0FfUG9sbCBpcyBydW5uaW5nLAogICAgICAgICAgICAgICB3ZSBuZWVkIHRvIGZha2UgdGhlIG9jY3VycmVuY2Ugb2YgdGhlIHZlcnRpY2FsIHJlZnJlc2ggKi8KICAgICAgICAgICAgaWYgKGxwZGRyYXcpIHsKICAgICAgICAgICAgICAgIHJldD12Z2FfcmVmcmVzaD8weDAwOjB4MDg7CiAgICAgICAgICAgICAgICB2Z2FfcmVmcmVzaD0wOwogICAgICAgICAgICB9IGVsc2UgcmV0PTB4MDg7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHJldD0weGZmOwogICAgfQogICAgcmV0dXJuIHJldDsKfQo=