LyoKICogVkdBIGhhcmR3YXJlIGVtdWxhdGlvbgogKiAKICogQ29weXJpZ2h0IDE5OTggT3ZlIEvldmVuICh3aXRoIHNvbWUgaGVscCBmcm9tIE1hcmN1cyBNZWlzc25lcikKICoKICovCgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5nZGkuaCIKI2luY2x1ZGUgIndpbnVzZXIuaCIKI2luY2x1ZGUgIndpbmNvbi5oIgojaW5jbHVkZSAibWlzY2VtdS5oIgojaW5jbHVkZSAiZG9zZXhlLmgiCiNpbmNsdWRlICJ2Z2EuaCIKI2luY2x1ZGUgImRkcmF3LmgiCiNpbmNsdWRlICJzZXJ2aWNlcy5oIgojaW5jbHVkZSAiZGVidWd0b29scy5oIgoKREVGQVVMVF9ERUJVR19DSEFOTkVMKGRkcmF3KTsKCnN0YXRpYyBJRGlyZWN0RHJhdyAqbHBkZHJhdyA9IE5VTEw7CnN0YXRpYyBJRGlyZWN0RHJhd1N1cmZhY2UgKmxwZGRzdXJmOwpzdGF0aWMgSURpcmVjdERyYXdQYWxldHRlICpscGRkcGFsOwpzdGF0aWMgRERTVVJGQUNFREVTQyBzZGVzYzsKc3RhdGljIExPTkcgdmdhX3BvbGxpbmcsdmdhX3JlZnJlc2g7CnN0YXRpYyBIQU5ETEUgcG9sbF90aW1lcjsKCnN0YXRpYyBpbnQgdmdhX3dpZHRoOwpzdGF0aWMgaW50IHZnYV9oZWlnaHQ7CnN0YXRpYyBpbnQgdmdhX2RlcHRoOwoKdHlwZWRlZiBIUkVTVUxUIChXSU5BUEkgKkRpcmVjdERyYXdDcmVhdGVQcm9jKShMUEdVSUQsTFBESVJFQ1REUkFXICosTFBVTktOT1dOKTsKc3RhdGljIERpcmVjdERyYXdDcmVhdGVQcm9jIHBEaXJlY3REcmF3Q3JlYXRlOwoKc3RhdGljIFBBTEVUVEVFTlRSWSB2Z2FfZGVmX3BhbGV0dGVbMjU2XT17Ci8qIHJlZCAgZ3JlZW4gIGJsdWUgKi8KICB7MHgwMCwgMHgwMCwgMHgwMH0sIC8qIDAgLSBCbGFjayAqLwogIHsweDAwLCAweDAwLCAweDgwfSwgLyogMSAtIEJsdWUgKi8KICB7MHgwMCwgMHg4MCwgMHgwMH0sIC8qIDIgLSBHcmVlbiAqLwogIHsweDAwLCAweDgwLCAweDgwfSwgLyogMyAtIEN5YW4gKi8KICB7MHg4MCwgMHgwMCwgMHgwMH0sIC8qIDQgLSBSZWQgKi8KICB7MHg4MCwgMHgwMCwgMHg4MH0sIC8qIDUgLSBNYWdlbnRhICovCiAgezB4ODAsIDB4ODAsIDB4MDB9LCAvKiA2IC0gQnJvd24gKi8KICB7MHhDMCwgMHhDMCwgMHhDMH0sIC8qIDcgLSBMaWdodCBncmF5ICovCiAgezB4ODAsIDB4ODAsIDB4ODB9LCAvKiA4IC0gRGFyayBncmF5ICovCiAgezB4MDAsIDB4MDAsIDB4RkZ9LCAvKiA5IC0gTGlnaHQgYmx1ZSAqLwogIHsweDAwLCAweEZGLCAweDAwfSwgLyogQSAtIExpZ2h0IGdyZWVuICovCiAgezB4MDAsIDB4RkYsIDB4RkZ9LCAvKiBCIC0gTGlnaHQgY3lhbiAqLwogIHsweEZGLCAweDAwLCAweDAwfSwgLyogQyAtIExpZ2h0IHJlZCAqLwogIHsweEZGLCAweDAwLCAweEZGfSwgLyogRCAtIExpZ2h0IG1hZ2VudGEgKi8KICB7MHhGRiwgMHhGRiwgMHgwMH0sIC8qIEUgLSBZZWxsb3cgKi8KICB7MHhGRiwgMHhGRiwgMHhGRn0sIC8qIEYgLSBXaGl0ZSAqLwogIHswLDAsMH0gLyogRklYTUU6IGEgc2VyaWVzIG9mIGNvbnRpbnVvdXMgcmFpbmJvdyBodWVzIHNob3VsZCBmb2xsb3cgKi8KfTsKCnN0YXRpYyB2b2lkIFZHQV9EZWluc3RhbGxUaW1lcih2b2lkKQp7CiAgICBpZiAocG9sbF90aW1lcikgewogICAgICAgIFNFUlZJQ0VfRGVsZXRlKCBwb2xsX3RpbWVyICk7CiAgICAgICAgcG9sbF90aW1lciA9IDA7CiAgICB9Cn0KCnN0YXRpYyB2b2lkIFZHQV9JbnN0YWxsVGltZXIodW5zaWduZWQgUmF0ZSkKewogICAgVkdBX0RlaW5zdGFsbFRpbWVyKCk7CiAgICBpZiAoIXBvbGxfdGltZXIpCiAgICAgICAgcG9sbF90aW1lciA9IFNFUlZJQ0VfQWRkVGltZXIoIFJhdGUsIFZHQV9Qb2xsLCAwICk7Cn0KCkhBTkRMRSBWR0FfQWxwaGFDb25zb2xlKHZvaWQpCnsKICAgIC8qIHRoaXMgYXNzdW1lcyB0aGF0IG5vIFdpbjMyIHJlZGlyZWN0aW9uIGhhcyB0YWtlbiBwbGFjZSwgYnV0IHRoZW4gYWdhaW4sCiAgICAgKiBvbmx5IDE2LWJpdCBhcHBzIGFyZSBsaWtlbHkgdG8gdXNlIHRoaXMgcGFydCBvZiBXaW5lLi4uICovCiAgICByZXR1cm4gR2V0U3RkSGFuZGxlKFNURF9PVVRQVVRfSEFORExFKTsKfQoKY2hhcipWR0FfQWxwaGFCdWZmZXIodm9pZCkKewogICAgcmV0dXJuIERPU01FTV9NYXBEb3NUb0xpbmVhcigweGI4MDAwKTsKfQoKLyoqKiBHUkFQSElDUyBNT0RFICoqKi8KCnR5cGVkZWYgc3RydWN0IHsKICB1bnNpZ25lZCBYcmVzLCBZcmVzLCBEZXB0aDsKICBpbnQgcmV0Owp9IE1vZGVTZXQ7CgpzdGF0aWMgdm9pZCBXSU5BUEkgVkdBX0RvU2V0TW9kZShVTE9OR19QVFIgYXJnKQp7CiAgICBMUkVTVUxUCXJlczsKICAgIEhXTkQJaHduZDsKICAgIE1vZGVTZXQgKnBhciA9IChNb2RlU2V0ICopYXJnOwogICAgcGFyLT5yZXQ9MTsKCiAgICBpZiAobHBkZHJhdykgVkdBX0V4aXQoKTsKICAgIGlmICghbHBkZHJhdykgewogICAgICAgIGlmICghcERpcmVjdERyYXdDcmVhdGUpCiAgICAgICAgewogICAgICAgICAgICBITU9EVUxFIGhtb2QgPSBMb2FkTGlicmFyeUEoICJkZHJhdy5kbGwiICk7CiAgICAgICAgICAgIGlmIChobW9kKSBwRGlyZWN0RHJhd0NyZWF0ZSA9IChEaXJlY3REcmF3Q3JlYXRlUHJvYylHZXRQcm9jQWRkcmVzcyggaG1vZCwgIkRpcmVjdERyYXdDcmVhdGUiICk7CgkgICAgaWYgKCFwRGlyZWN0RHJhd0NyZWF0ZSkgewoJCUVSUigiQ2FuJ3QgbG9va3VwIERpcmVjdERyYXdDcmVhdGUgZnJvbSBkZHJhdy5kbGwuXG4iKTsKCQlyZXR1cm47CgkgICAgfQogICAgICAgIH0KICAgICAgICByZXMgPSBwRGlyZWN0RHJhd0NyZWF0ZShOVUxMLCZscGRkcmF3LE5VTEwpOwogICAgICAgIGlmICghbHBkZHJhdykgewogICAgICAgICAgICBFUlIoIkRpcmVjdERyYXcgaXMgbm90IGF2YWlsYWJsZSAocmVzID0gJWx4KVxuIixyZXMpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoJaHduZCA9IENyZWF0ZVdpbmRvd0V4QSgwLCJTVEFUSUMiLCJXSU5FRE9TIFZHQSIsV1NfUE9QVVB8V1NfQk9SREVSfFdTX0NBUFRJT058V1NfU1lTTUVOVSwwLDAscGFyLT5YcmVzLHBhci0+WXJlcywwLDAsMCxOVUxMKTsKCWlmICghaHduZCkgewoJICAgIEVSUigiRmFpbGVkIHRvIGNyZWF0ZSB1c2VyIHdpbmRvdy5cbiIpOwoJfQogICAgICAgIGlmICgocmVzPUlEaXJlY3REcmF3X1NldENvb3BlcmF0aXZlTGV2ZWwobHBkZHJhdyxod25kLEREU0NMX0ZVTExTQ1JFRU58RERTQ0xfRVhDTFVTSVZFKSkpIHsKCSAgICBFUlIoIkNvdWxkIG5vdCBzZXQgY29vcGVyYXRpdmUgbGV2ZWwgdG8gZXhjbHVzaXZlICglbHgpXG4iLHJlcyk7Cgl9CgogICAgICAgIGlmICgocmVzPUlEaXJlY3REcmF3X1NldERpc3BsYXlNb2RlKGxwZGRyYXcscGFyLT5YcmVzLHBhci0+WXJlcyxwYXItPkRlcHRoKSkpIHsKICAgICAgICAgICAgRVJSKCJEaXJlY3REcmF3IGRvZXMgbm90IHN1cHBvcnQgcmVxdWVzdGVkIGRpc3BsYXkgbW9kZSAoJWR4JWR4JWQpLCByZXMgPSAlbHghXG4iLHBhci0+WHJlcyxwYXItPllyZXMscGFyLT5EZXB0aCxyZXMpOwogICAgICAgICAgICBJRGlyZWN0RHJhd19SZWxlYXNlKGxwZGRyYXcpOwogICAgICAgICAgICBscGRkcmF3PU5VTEw7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHJlcz1JRGlyZWN0RHJhd19DcmVhdGVQYWxldHRlKGxwZGRyYXcsRERQQ0FQU184QklULE5VTEwsJmxwZGRwYWwsTlVMTCk7CiAgICAgICAgaWYgKHJlcykgewoJICAgIEVSUigiQ291bGQgbm90IGNyZWF0ZSBwYWxldHRlIChyZXMgPSAlbHgpXG4iLHJlcyk7CiAgICAgICAgICAgIElEaXJlY3REcmF3X1JlbGVhc2UobHBkZHJhdyk7CiAgICAgICAgICAgIGxwZGRyYXc9TlVMTDsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBpZiAoKHJlcz1JRGlyZWN0RHJhd1BhbGV0dGVfU2V0RW50cmllcyhscGRkcGFsLDAsMCwyNTYsdmdhX2RlZl9wYWxldHRlKSkpIHsKICAgICAgICAgICAgRVJSKCJDb3VsZCBub3Qgc2V0IGRlZmF1bHQgcGFsZXR0ZSBlbnRyaWVzIChyZXMgPSAlbHgpXG4iLCByZXMpOwogICAgICAgIH0KCiAgICAgICAgbWVtc2V0KCZzZGVzYywwLHNpemVvZihzZGVzYykpOwogICAgICAgIHNkZXNjLmR3U2l6ZT1zaXplb2Yoc2Rlc2MpOwoJc2Rlc2MuZHdGbGFncyA9IEREU0RfQ0FQUzsKCXNkZXNjLmRkc0NhcHMuZHdDYXBzID0gRERTQ0FQU19QUklNQVJZU1VSRkFDRTsKICAgICAgICBpZiAoSURpcmVjdERyYXdfQ3JlYXRlU3VyZmFjZShscGRkcmF3LCZzZGVzYywmbHBkZHN1cmYsTlVMTCl8fCghbHBkZHN1cmYpKSB7CiAgICAgICAgICAgIEVSUigiRGlyZWN0RHJhdyBzdXJmYWNlIGlzIG5vdCBhdmFpbGFibGVcbiIpOwogICAgICAgICAgICBJRGlyZWN0RHJhd19SZWxlYXNlKGxwZGRyYXcpOwogICAgICAgICAgICBscGRkcmF3PU5VTEw7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgSURpcmVjdERyYXdTdXJmYWNlX1NldFBhbGV0dGUobHBkZHN1cmYsbHBkZHBhbCk7CiAgICAgICAgdmdhX3JlZnJlc2g9MDsKICAgICAgICAvKiBwb2xsIGV2ZXJ5IDIwbXMgKDUwZnBzIHNob3VsZCBwcm92aWRlIGFkZXF1YXRlIHJlc3BvbnNpdmVuZXNzKSAqLwogICAgICAgIFZHQV9JbnN0YWxsVGltZXIoMjApOwogICAgfQogICAgcGFyLT5yZXQ9MDsKICAgIHJldHVybjsKfQoKaW50IFZHQV9TZXRNb2RlKHVuc2lnbmVkIFhyZXMsdW5zaWduZWQgWXJlcyx1bnNpZ25lZCBEZXB0aCkKewogICAgTW9kZVNldCBwYXI7CgogICAgdmdhX3dpZHRoID0gWHJlczsKICAgIHZnYV9oZWlnaHQgPSBZcmVzOwogICAgdmdhX2RlcHRoID0gRGVwdGg7CgogICAgaWYoWHJlcyA+PSA2NDAgfHwgWXJlcyA+PSA0ODApIHsKICAgICAgcGFyLlhyZXMgPSBYcmVzOwogICAgICBwYXIuWXJlcyA9IFlyZXM7CiAgICB9IGVsc2UgewogICAgICBwYXIuWHJlcyA9IDY0MDsKICAgICAgcGFyLllyZXMgPSA0ODA7CiAgICB9CgogICAgcGFyLkRlcHRoID0gKERlcHRoIDwgOCkgPyA4IDogRGVwdGg7CgogICAgTVpfUnVuSW5UaHJlYWQoVkdBX0RvU2V0TW9kZSwgKFVMT05HX1BUUikmcGFyKTsKICAgIHJldHVybiBwYXIucmV0Owp9CgppbnQgVkdBX0dldE1vZGUodW5zaWduZWQqSGVpZ2h0LHVuc2lnbmVkKldpZHRoLHVuc2lnbmVkKkRlcHRoKQp7CiAgICBpZiAoIWxwZGRyYXcpIHJldHVybiAxOwogICAgaWYgKCFscGRkc3VyZikgcmV0dXJuIDE7CiAgICBpZiAoSGVpZ2h0KSAqSGVpZ2h0PXNkZXNjLmR3SGVpZ2h0OwogICAgaWYgKFdpZHRoKSAqV2lkdGg9c2Rlc2MuZHdXaWR0aDsKICAgIGlmIChEZXB0aCkgKkRlcHRoPXNkZXNjLmRkcGZQaXhlbEZvcm1hdC51MS5kd1JHQkJpdENvdW50OwogICAgcmV0dXJuIDA7Cn0KCnN0YXRpYyB2b2lkIFdJTkFQSSBWR0FfRG9FeGl0KFVMT05HX1BUUiBhcmcpCnsKICAgIFZHQV9EZWluc3RhbGxUaW1lcigpOwogICAgSURpcmVjdERyYXdTdXJmYWNlX1NldFBhbGV0dGUobHBkZHN1cmYsTlVMTCk7CiAgICBJRGlyZWN0RHJhd1N1cmZhY2VfUmVsZWFzZShscGRkc3VyZik7CiAgICBscGRkc3VyZj1OVUxMOwogICAgSURpcmVjdERyYXdQYWxldHRlX1JlbGVhc2UobHBkZHBhbCk7CiAgICBscGRkcGFsPU5VTEw7CiAgICBJRGlyZWN0RHJhd19SZWxlYXNlKGxwZGRyYXcpOwogICAgbHBkZHJhdz1OVUxMOwp9Cgp2b2lkIFZHQV9FeGl0KHZvaWQpCnsKICAgIGlmIChscGRkcmF3KSBNWl9SdW5JblRocmVhZChWR0FfRG9FeGl0LCAwKTsKfQoKdm9pZCBWR0FfU2V0UGFsZXR0ZShQQUxFVFRFRU5UUlkqcGFsLGludCBzdGFydCxpbnQgbGVuKQp7CiAgICBpZiAoIWxwZGRyYXcpIHJldHVybjsKICAgIElEaXJlY3REcmF3UGFsZXR0ZV9TZXRFbnRyaWVzKGxwZGRwYWwsMCxzdGFydCxsZW4scGFsKTsKfQoKdm9pZCBWR0FfU2V0UXVhZFBhbGV0dGUoUkdCUVVBRCpjb2xvcixpbnQgc3RhcnQsaW50IGxlbikKewogICAgUEFMRVRURUVOVFJZIHBhbFsyNTZdOwogICAgaW50IGM7CgogICAgaWYgKCFscGRkcmF3KSByZXR1cm47CiAgICBmb3IgKGM9MDsgYzxsZW47IGMrKykgewogICAgICAgIHBhbFtjXS5wZVJlZCAgPWNvbG9yW2NdLnJnYlJlZDsKICAgICAgICBwYWxbY10ucGVHcmVlbj1jb2xvcltjXS5yZ2JHcmVlbjsKICAgICAgICBwYWxbY10ucGVCbHVlID1jb2xvcltjXS5yZ2JCbHVlOwogICAgICAgIHBhbFtjXS5wZUZsYWdzPTA7CiAgICB9CiAgICBJRGlyZWN0RHJhd1BhbGV0dGVfU2V0RW50cmllcyhscGRkcGFsLDAsc3RhcnQsbGVuLHBhbCk7Cn0KCkxQU1RSIFZHQV9Mb2NrKHVuc2lnbmVkKlBpdGNoLHVuc2lnbmVkKkhlaWdodCx1bnNpZ25lZCpXaWR0aCx1bnNpZ25lZCpEZXB0aCkKewogICAgaWYgKCFscGRkcmF3KSByZXR1cm4gTlVMTDsKICAgIGlmICghbHBkZHN1cmYpIHJldHVybiBOVUxMOwogICAgaWYgKElEaXJlY3REcmF3U3VyZmFjZV9Mb2NrKGxwZGRzdXJmLE5VTEwsJnNkZXNjLDAsMCkpIHsKICAgICAgICBFUlIoImNvdWxkIG5vdCBsb2NrIHN1cmZhY2UhXG4iKTsKICAgICAgICByZXR1cm4gTlVMTDsKICAgIH0KICAgIGlmIChQaXRjaCkgKlBpdGNoPXNkZXNjLnUxLmxQaXRjaDsKICAgIGlmIChIZWlnaHQpICpIZWlnaHQ9c2Rlc2MuZHdIZWlnaHQ7CiAgICBpZiAoV2lkdGgpICpXaWR0aD1zZGVzYy5kd1dpZHRoOwogICAgaWYgKERlcHRoKSAqRGVwdGg9c2Rlc2MuZGRwZlBpeGVsRm9ybWF0LnUxLmR3UkdCQml0Q291bnQ7CiAgICByZXR1cm4gc2Rlc2MubHBTdXJmYWNlOwp9Cgp2b2lkIFZHQV9VbmxvY2sodm9pZCkKewogICAgSURpcmVjdERyYXdTdXJmYWNlX1VubG9jayhscGRkc3VyZixzZGVzYy5scFN1cmZhY2UpOwp9CgovKioqIFRFWFQgTU9ERSAqKiovCgppbnQgVkdBX1NldEFscGhhTW9kZSh1bnNpZ25lZCBYcmVzLHVuc2lnbmVkIFlyZXMpCnsKICAgIENPT1JEIHNpejsKCiAgICBpZiAobHBkZHJhdykgVkdBX0V4aXQoKTsKCiAgICAvKiB0aGUgeHRlcm0gaXMgc2xvdywgc28gcmVmcmVzaCBvbmx5IGV2ZXJ5IDIwMG1zICg1ZnBzKSAqLwogICAgVkdBX0luc3RhbGxUaW1lcigyMDApOwoKICAgIHNpei5YID0gWHJlczsKICAgIHNpei5ZID0gWXJlczsKICAgIFNldENvbnNvbGVTY3JlZW5CdWZmZXJTaXplKFZHQV9BbHBoYUNvbnNvbGUoKSxzaXopOwogICAgcmV0dXJuIDA7Cn0KCnZvaWQgVkdBX0dldEFscGhhTW9kZSh1bnNpZ25lZCpYcmVzLHVuc2lnbmVkKllyZXMpCnsKICAgIENPTlNPTEVfU0NSRUVOX0JVRkZFUl9JTkZPIGluZm87CiAgICBHZXRDb25zb2xlU2NyZWVuQnVmZmVySW5mbyhWR0FfQWxwaGFDb25zb2xlKCksJmluZm8pOwogICAgaWYgKFhyZXMpICpYcmVzPWluZm8uZHdTaXplLlg7CiAgICBpZiAoWXJlcykgKllyZXM9aW5mby5kd1NpemUuWTsKfQoKdm9pZCBWR0FfU2V0Q3Vyc29yUG9zKHVuc2lnbmVkIFgsdW5zaWduZWQgWSkKewogICAgQ09PUkQgcG9zOwoKICAgIGlmICghcG9sbF90aW1lcikgVkdBX1NldEFscGhhTW9kZSg4MCwgMjUpOwogICAgcG9zLlggPSBYOwogICAgcG9zLlkgPSBZOwogICAgU2V0Q29uc29sZUN1cnNvclBvc2l0aW9uKFZHQV9BbHBoYUNvbnNvbGUoKSxwb3MpOwp9Cgp2b2lkIFZHQV9HZXRDdXJzb3JQb3ModW5zaWduZWQqWCx1bnNpZ25lZCpZKQp7CiAgICBDT05TT0xFX1NDUkVFTl9CVUZGRVJfSU5GTyBpbmZvOwogICAgR2V0Q29uc29sZVNjcmVlbkJ1ZmZlckluZm8oVkdBX0FscGhhQ29uc29sZSgpLCZpbmZvKTsKICAgIGlmIChYKSAqWD1pbmZvLmR3Q3Vyc29yUG9zaXRpb24uWDsKICAgIGlmIChZKSAqWT1pbmZvLmR3Q3Vyc29yUG9zaXRpb24uWTsKfQoKdm9pZCBWR0FfV3JpdGVDaGFycyh1bnNpZ25lZCBYLHVuc2lnbmVkIFksdW5zaWduZWQgY2gsaW50IGF0dHIsaW50IGNvdW50KQp7CiAgICB1bnNpZ25lZCBYUiwgWVI7CiAgICBjaGFyKmRhdDsKCiAgICBWR0FfR2V0QWxwaGFNb2RlKCZYUiwgJllSKTsKICAgIGRhdCA9IFZHQV9BbHBoYUJ1ZmZlcigpICsgKChYUipZICsgWCkgKiAyKTsKICAgIC8qIEZJWE1FOiBhbHNvIGNhbGwgV3JpdGVDb25zb2xlT3V0cHV0QSwgZm9yIGJldHRlciByZXNwb25zaXZlbmVzcyAqLwogICAgd2hpbGUgKGNvdW50LS0pIHsKICAgICAgICAqZGF0KysgPSBjaDsKICAgICAgICBpZiAoYXR0cj49MCkgKmRhdCA9IGF0dHI7CiAgICAgICAgZGF0Kys7CiAgICB9Cn0KCi8qKiogQ09OVFJPTCAqKiovCgpzdGF0aWMgdm9pZCBWR0FfUG9sbF9HcmFwaGljcyh2b2lkKQp7CiAgdW5zaWduZWQgaW50IFBpdGNoLCBIZWlnaHQsIFdpZHRoLCBYLCBZOwogIGNoYXIgKnN1cmY7CiAgY2hhciAqZGF0ID0gRE9TTUVNX01hcERvc1RvTGluZWFyKDB4YTAwMDApOwoKICBzdXJmID0gVkdBX0xvY2soJlBpdGNoLCZIZWlnaHQsJldpZHRoLE5VTEwpOwogIGlmICghc3VyZikgcmV0dXJuOwoKICBpZih2Z2Ffd2lkdGggPT0gMzIwICYmIHZnYV9kZXB0aCA8PSA0KQogICAgZm9yIChZPTA7IFk8dmdhX2hlaWdodDsgWSsrLHN1cmYrPVBpdGNoKjIsZGF0Kz12Z2Ffd2lkdGgvOCkgewogICAgICBmb3IoWD0wOyBYPHZnYV93aWR0aDsgWCs9OCkgewogICAgICAgaW50IG9mZnNldCA9IFgvODsKICAgICAgIGludCBaOwogICAgICAgZm9yKFo9MDsgWjw4OyBaKyspIHsKICAgICAgICAgaW50IGIwID0gIChkYXRbb2Zmc2V0XSA+PiBaKSAmIDB4MTsKICAgICAgICAgaW50IGluZGV4ID0gNy1aOwogICAgICAgICBzdXJmWyhYK2luZGV4KSoyXSA9IGIwOwogICAgICAgICBzdXJmWyhYK2luZGV4KSoyKzFdID0gYjA7CiAgICAgICAgIHN1cmZbKFgraW5kZXgpKjIrUGl0Y2hdID0gYjA7CiAgICAgICAgIHN1cmZbKFgraW5kZXgpKjIrUGl0Y2grMV0gPSBiMDsKICAgICAgIH0KICAgICAgfQogICAgfQoKICBpZih2Z2Ffd2lkdGggPT0gMzIwICYmIHZnYV9kZXB0aCA9PSA4KQogICAgZm9yIChZPTA7IFk8dmdhX2hlaWdodDsgWSsrLHN1cmYrPVBpdGNoKjIsZGF0Kz12Z2Ffd2lkdGgpIHsKICAgICAgZm9yKFg9MDsgWDx2Z2Ffd2lkdGg7IFgrKykgewogICAgICAgaW50IGIwID0gZGF0W1hdOwogICAgICAgc3VyZltYKjJdID0gYjA7CiAgICAgICBzdXJmW1gqMisxXSA9IGIwOwogICAgICAgc3VyZltYKjIrUGl0Y2hdID0gYjA7CiAgICAgICBzdXJmW1gqMitQaXRjaCsxXSA9IGIwOwogICAgICB9CiAgICB9CgogIGlmKHZnYV9kZXB0aCA8PSA0KQogICAgZm9yIChZPTA7IFk8dmdhX2hlaWdodDsgWSsrLHN1cmYrPVBpdGNoLGRhdCs9dmdhX3dpZHRoLzgpIHsKICAgICAgZm9yKFg9MDsgWDx2Z2Ffd2lkdGg7IFgrPTgpIHsKICAgICAgIGludCBvZmZzZXQgPSBYLzg7CiAgICAgICBpbnQgWjsKICAgICAgIGZvcihaPTA7IFo8ODsgWisrKSB7CiAgICAgICAgIGludCBiMCA9ICAoZGF0W29mZnNldF0gPj4gWikgJiAweDE7CiAgICAgICAgIGludCBpbmRleCA9IDctWjsKICAgICAgICAgc3VyZltYK2luZGV4XSA9IGIwOwogICAgICAgfQogICAgICB9CiAgICB9CgogIFZHQV9VbmxvY2soKTsKfQoKCnZvaWQgQ0FMTEJBQ0sgVkdBX1BvbGwoIFVMT05HX1BUUiBhcmcgKQp7CiAgICBjaGFyICpkYXQ7CiAgICB1bnNpZ25lZCBpbnQgSGVpZ2h0LFdpZHRoLFksWDsKCiAgICBpZiAoIUludGVybG9ja2VkRXhjaGFuZ2VBZGQoJnZnYV9wb2xsaW5nLCAxKSkgewogICAgICAgIC8qIEZJWE1FOiBvcHRpbWl6ZSBieSBkb2luZyB0aGlzIG9ubHkgaWYgdGhlIGRhdGEgaGFzIGFjdHVhbGx5IGNoYW5nZWQKICAgICAgICAgKiAgICAgICAgKGluIGEgd2F5IHNpbWlsYXIgdG8gRElCU2VjdGlvbiwgcGVyaGFwcykgKi8KICAgICAgICBpZiAobHBkZHJhdykgewogICAgICAgICBWR0FfUG9sbF9HcmFwaGljcygpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvKiB0ZXh0IG1vZGUgKi8KICAgICAgICAgIENIQVJfSU5GTyBjaFs4MF07CiAgICAgICAgICBDT09SRCBzaXosIG9mZjsKICAgICAgICAgIFNNQUxMX1JFQ1QgZGVzdDsKICAgICAgICAgIEhBTkRMRSBjb24gPSBWR0FfQWxwaGFDb25zb2xlKCk7CgogICAgICAgICAgVkdBX0dldEFscGhhTW9kZSgmV2lkdGgsJkhlaWdodCk7CiAgICAgICAgICBkYXQgPSBWR0FfQWxwaGFCdWZmZXIoKTsKICAgICAgICAgIHNpei5YID0gODA7IHNpei5ZID0gMTsKICAgICAgICAgIG9mZi5YID0gMDsgb2ZmLlkgPSAwOwogICAgICAgICAgLyogY29weSBmcm9tIHZpcnR1YWwgVkdBIGZyYW1lIGJ1ZmZlciB0byBjb25zb2xlICovCiAgICAgICAgICBmb3IgKFk9MDsgWTxIZWlnaHQ7IFkrKykgewogICAgICAgICAgICAgIGRlc3QuVG9wPVk7IGRlc3QuQm90dG9tPVk7CiAgICAgICAgICAgICAgZm9yIChYPTA7IFg8V2lkdGg7IFgrKykgewogICAgICAgICAgICAgICAgICBjaFtYXS5DaGFyLkFzY2lpQ2hhciA9ICpkYXQrKzsKCQkgIC8qIFdyaXRlQ29uc29sZU91dHB1dEEgZG9lc24ndCBsaWtlICJkZWFkIiBjaGFycyAqLwoJCSAgaWYgKGNoW1hdLkNoYXIuQXNjaWlDaGFyID09ICdcMCcpCgkJICAgICAgY2hbWF0uQ2hhci5Bc2NpaUNoYXIgPSAnICc7CiAgICAgICAgICAgICAgICAgIGNoW1hdLkF0dHJpYnV0ZXMgPSAqZGF0Kys7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGRlc3QuTGVmdD0wOyBkZXN0LlJpZ2h0PVdpZHRoKzE7CiAgICAgICAgICAgICAgV3JpdGVDb25zb2xlT3V0cHV0QShjb24sIGNoLCBzaXosIG9mZiwgJmRlc3QpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB2Z2FfcmVmcmVzaD0xOwogICAgfQogICAgSW50ZXJsb2NrZWREZWNyZW1lbnQoJnZnYV9wb2xsaW5nKTsKfQoKc3RhdGljIEJZVEUgcGFscmVnLHBhbGNudDsKc3RhdGljIFBBTEVUVEVFTlRSWSBwYWxkYXQ7Cgp2b2lkIFZHQV9pb3BvcnRfb3V0KCBXT1JEIHBvcnQsIEJZVEUgdmFsICkKewogICAgc3dpdGNoIChwb3J0KSB7CiAgICAgICAgY2FzZSAweDNjODoKICAgICAgICAgICAgcGFscmVnPXZhbDsgcGFsY250PTA7IGJyZWFrOwogICAgICAgIGNhc2UgMHgzYzk6CiAgICAgICAgICAgICgoQllURSopJnBhbGRhdClbcGFsY250KytdPXZhbCA8PCAyOwogICAgICAgICAgICBpZiAocGFsY250PT0zKSB7CiAgICAgICAgICAgICAgICBWR0FfU2V0UGFsZXR0ZSgmcGFsZGF0LHBhbHJlZysrLDEpOwogICAgICAgICAgICAgICAgcGFsY250PTA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICB9Cn0KCkJZVEUgVkdBX2lvcG9ydF9pbiggV09SRCBwb3J0ICkKewogICAgQllURSByZXQ7CgogICAgc3dpdGNoIChwb3J0KSB7CiAgICAgICAgY2FzZSAweDNkYToKICAgICAgICAgICAgLyogc2luY2Ugd2UgZG9uJ3QgKHlldD8pIHNlcnZlIERPUyBWTSByZXF1ZXN0cyB3aGlsZSBWR0FfUG9sbCBpcyBydW5uaW5nLAogICAgICAgICAgICAgICB3ZSBuZWVkIHRvIGZha2UgdGhlIG9jY3VycmVuY2Ugb2YgdGhlIHZlcnRpY2FsIHJlZnJlc2ggKi8KICAgICAgICAgICAgcmV0PXZnYV9yZWZyZXNoPzB4MDA6MHgwODsKICAgICAgICAgICAgdmdhX3JlZnJlc2g9MDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0PTB4ZmY7CiAgICB9CiAgICByZXR1cm4gcmV0Owp9Cgp2b2lkIFZHQV9DbGVhbih2b2lkKQp7CiAgICBWR0FfRXhpdCgpOwogICAgVkdBX0RlaW5zdGFsbFRpbWVyKCk7Cn0K