Ly8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyBCaXRtYXAgcm90YXRpb24gdXNpbmcgQi1TcGxpbmVzCi8vCi8vIERlc2lnbiBhbmQgaW1wbGVtZW50YXRpb24gYnkKLy8gLSBQaGlsaXBwZSBUaOl2ZW5heiAocGhpbGlwcGUudGhldmVuYXpAZXBmbC5jaCkKLy8gQWRhcHRhdGlvbiBmb3IgRnJlZUltYWdlIGJ5Ci8vIC0gSGVydukgRHJvbG9uIChkcm9sb25AaW5mb25pZS5mcikKLy8KLy8gVGhpcyBmaWxlIGlzIHBhcnQgb2YgRnJlZUltYWdlIDMKLy8KLy8gQ09WRVJFRCBDT0RFIElTIFBST1ZJREVEIFVOREVSIFRISVMgTElDRU5TRSBPTiBBTiAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRZCi8vIE9GIEFOWSBLSU5ELCBFSVRIRVIgRVhQUkVTU0VEIE9SIElNUExJRUQsIElOQ0xVRElORywgV0lUSE9VVCBMSU1JVEFUSU9OLCBXQVJSQU5USUVTCi8vIFRIQVQgVEhFIENPVkVSRUQgQ09ERSBJUyBGUkVFIE9GIERFRkVDVFMsIE1FUkNIQU5UQUJMRSwgRklUIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRQovLyBPUiBOT04tSU5GUklOR0lORy4gVEhFIEVOVElSRSBSSVNLIEFTIFRPIFRIRSBRVUFMSVRZIEFORCBQRVJGT1JNQU5DRSBPRiBUSEUgQ09WRVJFRAovLyBDT0RFIElTIFdJVEggWU9VLiBTSE9VTEQgQU5ZIENPVkVSRUQgQ09ERSBQUk9WRSBERUZFQ1RJVkUgSU4gQU5ZIFJFU1BFQ1QsIFlPVSAoTk9UCi8vIFRIRSBJTklUSUFMIERFVkVMT1BFUiBPUiBBTlkgT1RIRVIgQ09OVFJJQlVUT1IpIEFTU1VNRSBUSEUgQ09TVCBPRiBBTlkgTkVDRVNTQVJZCi8vIFNFUlZJQ0lORywgUkVQQUlSIE9SIENPUlJFQ1RJT04uIFRISVMgRElTQ0xBSU1FUiBPRiBXQVJSQU5UWSBDT05TVElUVVRFUyBBTiBFU1NFTlRJQUwKLy8gUEFSVCBPRiBUSElTIExJQ0VOU0UuIE5PIFVTRSBPRiBBTlkgQ09WRVJFRCBDT0RFIElTIEFVVEhPUklaRUQgSEVSRVVOREVSIEVYQ0VQVCBVTkRFUgovLyBUSElTIERJU0NMQUlNRVIuCi8vCi8vIFVzZSBhdCB5b3VyIG93biByaXNrIQovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovKiAKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpUaGlzIGNvZGUgd2FzIHRha2VuIGFuZCBhZGFwdGVkIGZyb20gdGhlIGZvbGxvd2luZyByZWZlcmVuY2UgOiAKClsxXSBQaGlsaXBwZSBUaOl2ZW5heiwgU3BsaW5lIGludGVycG9sYXRpb24sIGEgQyBzb3VyY2UgY29kZSAKaW1wbGVtZW50YXRpb24uIGh0dHA6Ly9iaWd3d3cuZXBmbC5jaC90aGV2ZW5hei8KCkl0IGltcGxlbWVudHMgaWRlYXMgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgcGFwZXJzIDogCgpbMl0gVW5zZXIgTS4sIFNwbGluZXM6IEEgUGVyZmVjdCBGaXQgZm9yIFNpZ25hbCBhbmQgSW1hZ2UgUHJvY2Vzc2luZy4gCklFRUUgU2lnbmFsIFByb2Nlc3NpbmcgTWFnYXppbmUsIHZvbC4gMTYsIG5vLiA2LCBwcC4gMjItMzgsIE5vdmVtYmVyIDE5OTkuIAoKWzNdIFVuc2VyIE0uLCBBbGRyb3ViaSBBLiwgRWRlbiBNLiwgQi1TcGxpbmUgU2lnbmFsIFByb2Nlc3Npbmc6IFBhcnQgSS0tVGhlb3J5LgpJRUVFIFRyYW5zYWN0aW9ucyBvbiBTaWduYWwgUHJvY2Vzc2luZywgdm9sLiA0MSwgbm8uIDIsIHBwLiA4MjEtODMyLCBGZWJydWFyeSAxOTkzLiAKCls0XSBVbnNlciBNLiwgQWxkcm91YmkgQS4sIEVkZW4gTS4sIEItU3BsaW5lIFNpZ25hbCBQcm9jZXNzaW5nOiBQYXJ0IElJLS1FZmZpY2llbnQgRGVzaWduIGFuZCBBcHBsaWNhdGlvbnMuCklFRUUgVHJhbnNhY3Rpb25zIG9uIFNpZ25hbCBQcm9jZXNzaW5nLCB2b2wuIDQxLCBuby4gMiwgcHAuIDgzNC04NDgsIEZlYnJ1YXJ5IDE5OTMuCgo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IAoqLwoKCiNpbmNsdWRlIDxmbG9hdC5oPgojaW5jbHVkZSAiRnJlZUltYWdlLmgiCiNpbmNsdWRlICJVdGlsaXRpZXMuaCIKCiNkZWZpbmUgUEkJKChkb3VibGUpMy4xNDE1OTI2NTM1ODk3OTMyMzg0NjI2NDMzODMyNzk1MDI4ODQxOTcxNjkzOTkzNzUxMCkKCiNkZWZpbmUgUk9UQVRFX1FVQURSQVRJQyAyTAkvLyBVc2UgQi1zcGxpbmVzIG9mIGRlZ3JlZSAyIChxdWFkcmF0aWMgaW50ZXJwb2xhdGlvbikKI2RlZmluZSBST1RBVEVfQ1VCSUMgICAgIDNMCS8vIFVzZSBCLXNwbGluZXMgb2YgZGVncmVlIDMgKGN1YmljIGludGVycG9sYXRpb24pCiNkZWZpbmUgUk9UQVRFX1FVQVJUSUMgICA0TAkvLyBVc2UgQi1zcGxpbmVzIG9mIGRlZ3JlZSA0IChxdWFydGljIGludGVycG9sYXRpb24pCiNkZWZpbmUgUk9UQVRFX1FVSU5USUMgICA1TAkvLyBVc2UgQi1zcGxpbmVzIG9mIGRlZ3JlZSA1IChxdWludGljIGludGVycG9sYXRpb24pCgoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwovLyBQcm90b3R5cGVzIGRlZmluaXRpb24KCnN0YXRpYyB2b2lkIENvbnZlcnRUb0ludGVycG9sYXRpb25Db2VmZmljaWVudHMoZG91YmxlICpjLCBsb25nIERhdGFMZW5ndGgsIGRvdWJsZSAqeiwgbG9uZyBOYlBvbGVzLAlkb3VibGUgVG9sZXJhbmNlKTsKc3RhdGljIGRvdWJsZSBJbml0aWFsQ2F1c2FsQ29lZmZpY2llbnQoZG91YmxlICpjLCBsb25nIERhdGFMZW5ndGgsIGRvdWJsZSB6LCBkb3VibGUgVG9sZXJhbmNlKTsKc3RhdGljIHZvaWQgR2V0Q29sdW1uKGRvdWJsZSAqSW1hZ2UsIGxvbmcgV2lkdGgsIGxvbmcgeCwgZG91YmxlICpMaW5lLCBsb25nIEhlaWdodCk7CnN0YXRpYyB2b2lkCUdldFJvdyhkb3VibGUgKkltYWdlLCBsb25nIHksIGRvdWJsZSAqTGluZSwgbG9uZyBXaWR0aCk7CnN0YXRpYyBkb3VibGUgSW5pdGlhbEFudGlDYXVzYWxDb2VmZmljaWVudChkb3VibGUgKmMsIGxvbmcgRGF0YUxlbmd0aCwgZG91YmxlIHopOwpzdGF0aWMgdm9pZAlQdXRDb2x1bW4oZG91YmxlICpJbWFnZSwgbG9uZyBXaWR0aCwgbG9uZyB4LCBkb3VibGUgKkxpbmUsIGxvbmcgSGVpZ2h0KTsKc3RhdGljIHZvaWQJUHV0Um93KGRvdWJsZSAqSW1hZ2UsIGxvbmcgeSwgZG91YmxlICpMaW5lLCBsb25nIFdpZHRoKTsKc3RhdGljIGJvb2wgU2FtcGxlc1RvQ29lZmZpY2llbnRzKGRvdWJsZSAqSW1hZ2UsIGxvbmcgV2lkdGgsIGxvbmcgSGVpZ2h0LCBsb25nIHNwbGluZV9kZWdyZWUpOwpzdGF0aWMgZG91YmxlIEludGVycG9sYXRlZFZhbHVlKGRvdWJsZSAqQmNvZWZmLCBsb25nIFdpZHRoLCBsb25nIEhlaWdodCwgZG91YmxlIHgsIGRvdWJsZSB5LCBsb25nIHNwbGluZV9kZWdyZWUpOwoKc3RhdGljIEZJQklUTUFQICogUm90YXRlOEJpdChGSUJJVE1BUCAqZGliLCBkb3VibGUgYW5nbGUsIGRvdWJsZSB4X3NoaWZ0LCBkb3VibGUgeV9zaGlmdCwgZG91YmxlIHhfb3JpZ2luLCBkb3VibGUgeV9vcmlnaW4sIGxvbmcgc3BsaW5lX2RlZ3JlZSwgQk9PTCB1c2VfbWFzayk7CgovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vIENvZWZmaWNpZW50cyByb3V0aW5lcwoKLyoqCiBDb252ZXJ0VG9JbnRlcnBvbGF0aW9uQ29lZmZpY2llbnRzCgogQHBhcmFtIGMgSW5wdXQgc2FtcGxlcyAtLT4gb3V0cHV0IGNvZWZmaWNpZW50cwogQHBhcmFtIERhdGFMZW5ndGggTnVtYmVyIG9mIHNhbXBsZXMgb3IgY29lZmZpY2llbnRzCiBAcGFyYW0geiBQb2xlcwogQHBhcmFtIE5iUG9sZXMgTnVtYmVyIG9mIHBvbGVzCiBAcGFyYW0gVG9sZXJhbmNlIEFkbWlzc2libGUgcmVsYXRpdmUgZXJyb3IKKi8Kc3RhdGljIHZvaWQgCkNvbnZlcnRUb0ludGVycG9sYXRpb25Db2VmZmljaWVudHMoZG91YmxlICpjLCBsb25nIERhdGFMZW5ndGgsIGRvdWJsZSAqeiwgbG9uZyBOYlBvbGVzLAlkb3VibGUgVG9sZXJhbmNlKSB7Cglkb3VibGUJTGFtYmRhID0gMTsKCWxvbmcJbiwgazsKCgkvLyBzcGVjaWFsIGNhc2UgcmVxdWlyZWQgYnkgbWlycm9yIGJvdW5kYXJpZXMKCWlmKERhdGFMZW5ndGggPT0gMUwpIHsKCQlyZXR1cm47Cgl9CgkvLyBjb21wdXRlIHRoZSBvdmVyYWxsIGdhaW4KCWZvcihrID0gMEw7IGsgPCBOYlBvbGVzOyBrKyspIHsKCQlMYW1iZGEgPSBMYW1iZGEgKiAoMS4wIC0geltrXSkgKiAoMS4wIC0gMS4wIC8geltrXSk7Cgl9CgkvLyBhcHBseSB0aGUgZ2FpbiAKCWZvciAobiA9IDBMOyBuIDwgRGF0YUxlbmd0aDsgbisrKSB7CgkJY1tuXSAqPSBMYW1iZGE7Cgl9CgkvLyBsb29wIG92ZXIgYWxsIHBvbGVzIAoJZm9yIChrID0gMEw7IGsgPCBOYlBvbGVzOyBrKyspIHsKCQkvLyBjYXVzYWwgaW5pdGlhbGl6YXRpb24gCgkJY1swXSA9IEluaXRpYWxDYXVzYWxDb2VmZmljaWVudChjLCBEYXRhTGVuZ3RoLCB6W2tdLCBUb2xlcmFuY2UpOwoJCS8vIGNhdXNhbCByZWN1cnNpb24gCgkJZm9yIChuID0gMUw7IG4gPCBEYXRhTGVuZ3RoOyBuKyspIHsKCQkJY1tuXSArPSB6W2tdICogY1tuIC0gMUxdOwoJCX0KCQkvLyBhbnRpY2F1c2FsIGluaXRpYWxpemF0aW9uIAoJCWNbRGF0YUxlbmd0aCAtIDFMXSA9IEluaXRpYWxBbnRpQ2F1c2FsQ29lZmZpY2llbnQoYywgRGF0YUxlbmd0aCwgeltrXSk7CgkJLy8gYW50aWNhdXNhbCByZWN1cnNpb24gCgkJZm9yIChuID0gRGF0YUxlbmd0aCAtIDJMOyAwIDw9IG47IG4tLSkgewoJCQljW25dID0geltrXSAqIChjW24gKyAxTF0gLSBjW25dKTsKCQl9Cgl9Cn0gCgovKioKIEluaXRpYWxDYXVzYWxDb2VmZmljaWVudAoKIEBwYXJhbSBjIENvZWZmaWNpZW50cwogQHBhcmFtIERhdGFMZW5ndGggTnVtYmVyIG9mIGNvZWZmaWNpZW50cwogQHBhcmFtIHogQWN0dWFsIHBvbGUKIEBwYXJhbSBUb2xlcmFuY2UgQWRtaXNzaWJsZSByZWxhdGl2ZSBlcnJvcgogQHJldHVybgoqLwpzdGF0aWMgZG91YmxlIApJbml0aWFsQ2F1c2FsQ29lZmZpY2llbnQoZG91YmxlCSpjLCBsb25nIERhdGFMZW5ndGgsIGRvdWJsZQl6LCBkb3VibGUgVG9sZXJhbmNlKSB7Cglkb3VibGUJU3VtLCB6biwgejJuLCBpejsKCWxvbmcJbiwgSG9yaXpvbjsKCgkvLyB0aGlzIGluaXRpYWxpemF0aW9uIGNvcnJlc3BvbmRzIHRvIG1pcnJvciBib3VuZGFyaWVzIAoJSG9yaXpvbiA9IERhdGFMZW5ndGg7CglpZihUb2xlcmFuY2UgPiAwKSB7CgkJSG9yaXpvbiA9IChsb25nKWNlaWwobG9nKFRvbGVyYW5jZSkgLyBsb2coZmFicyh6KSkpOwoJfQoJaWYoSG9yaXpvbiA8IERhdGFMZW5ndGgpIHsKCQkvLyBhY2NlbGVyYXRlZCBsb29wCgkJem4gPSB6OwoJCVN1bSA9IGNbMF07CgkJZm9yIChuID0gMUw7IG4gPCBIb3Jpem9uOyBuKyspIHsKCQkJU3VtICs9IHpuICogY1tuXTsKCQkJem4gKj0gejsKCQl9CgkJcmV0dXJuKFN1bSk7Cgl9CgllbHNlIHsKCQkvLyBmdWxsIGxvb3AgCgkJem4gPSB6OwoJCWl6ID0gMS4wIC8gejsKCQl6Mm4gPSBwb3coeiwgKGRvdWJsZSkoRGF0YUxlbmd0aCAtIDFMKSk7CgkJU3VtID0gY1swXSArIHoybiAqIGNbRGF0YUxlbmd0aCAtIDFMXTsKCQl6Mm4gKj0gejJuICogaXo7CgkJZm9yIChuID0gMUw7IG4gPD0gRGF0YUxlbmd0aCAtIDJMOyBuKyspIHsKCQkJU3VtICs9ICh6biArIHoybikgKiBjW25dOwoJCQl6biAqPSB6OwoJCQl6Mm4gKj0gaXo7CgkJfQoJCXJldHVybihTdW0gLyAoMS4wIC0gem4gKiB6bikpOwoJfQp9CgovKioKIEdldENvbHVtbgoKIEBwYXJhbSBJbWFnZSBJbnB1dCBpbWFnZSBhcnJheQogQHBhcmFtIFdpZHRoIFdpZHRoIG9mIHRoZSBpbWFnZQogQHBhcmFtIHggeCBjb29yZGluYXRlIG9mIHRoZSBzZWxlY3RlZCBsaW5lCiBAcGFyYW0gTGluZSBPdXRwdXQgbGluZWFyIGFycmF5CiBAcGFyYW0gSGVpZ2h0IExlbmd0aCBvZiB0aGUgbGluZQoqLwpzdGF0aWMgdm9pZCAKR2V0Q29sdW1uKGRvdWJsZSAqSW1hZ2UsIGxvbmcgV2lkdGgsIGxvbmcgeCwgZG91YmxlICpMaW5lLCBsb25nIEhlaWdodCkgewoJbG9uZyB5OwoKCUltYWdlID0gSW1hZ2UgKyB4OwoJZm9yKHkgPSAwTDsgeSA8IEhlaWdodDsgeSsrKSB7CgkJTGluZVt5XSA9IChkb3VibGUpKkltYWdlOwoJCUltYWdlICs9IFdpZHRoOwoJfQp9CgovKioKIEdldFJvdwoKIEBwYXJhbSBJbWFnZSBJbnB1dCBpbWFnZSBhcnJheQogQHBhcmFtIHkgeSBjb29yZGluYXRlIG9mIHRoZSBzZWxlY3RlZCBsaW5lCiBAcGFyYW0gTGluZSBPdXRwdXQgbGluZWFyIGFycmF5CiBAcGFyYW0gV2lkdGggTGVuZ3RoIG9mIHRoZSBsaW5lCiovCnN0YXRpYyB2b2lkCQpHZXRSb3coZG91YmxlICpJbWFnZSwgbG9uZyB5LCBkb3VibGUgKkxpbmUsIGxvbmcgV2lkdGgpIHsKCWxvbmcJeDsKCglJbWFnZSA9IEltYWdlICsgKHkgKiBXaWR0aCk7Cglmb3IoeCA9IDBMOyB4IDwgV2lkdGg7IHgrKykgewoJCUxpbmVbeF0gPSAoZG91YmxlKSpJbWFnZSsrOwoJfQp9CgovKioKIEluaXRpYWxBbnRpQ2F1c2FsQ29lZmZpY2llbnQKCiBAcGFyYW0gYyBDb2VmZmljaWVudHMKIEBwYXJhbSBEYXRhTGVuZ3RoIE51bWJlciBvZiBzYW1wbGVzIG9yIGNvZWZmaWNpZW50cwogQHBhcmFtIHogQWN0dWFsIHBvbGUKIEByZXR1cm4KKi8Kc3RhdGljIGRvdWJsZSAKSW5pdGlhbEFudGlDYXVzYWxDb2VmZmljaWVudChkb3VibGUJKmMsIGxvbmcgRGF0YUxlbmd0aCwgZG91YmxlCXopIHsKCS8vIHRoaXMgaW5pdGlhbGl6YXRpb24gY29ycmVzcG9uZHMgdG8gbWlycm9yIGJvdW5kYXJpZXMKCXJldHVybigoeiAvICh6ICogeiAtIDEuMCkpICogKHogKiBjW0RhdGFMZW5ndGggLSAyTF0gKyBjW0RhdGFMZW5ndGggLSAxTF0pKTsKfQoKLyoqCiBQdXRDb2x1bW4KCiBAcGFyYW0gSW1hZ2UgT3V0cHV0IGltYWdlIGFycmF5CiBAcGFyYW0gV2lkdGggV2lkdGggb2YgdGhlIGltYWdlCiBAcGFyYW0geCB4IGNvb3JkaW5hdGUgb2YgdGhlIHNlbGVjdGVkIGxpbmUKIEBwYXJhbSBMaW5lIElucHV0IGxpbmVhciBhcnJheQogQHBhcmFtIEhlaWdodCBMZW5ndGggb2YgdGhlIGxpbmUgYW5kIGhlaWdodCBvZiB0aGUgaW1hZ2UKKi8Kc3RhdGljIHZvaWQJClB1dENvbHVtbihkb3VibGUgKkltYWdlLCBsb25nIFdpZHRoLCBsb25nIHgsIGRvdWJsZSAqTGluZSwgbG9uZyBIZWlnaHQpIHsKCWxvbmcJeTsKCglJbWFnZSA9IEltYWdlICsgeDsKCWZvcih5ID0gMEw7IHkgPCBIZWlnaHQ7IHkrKykgewoJCSpJbWFnZSA9IChkb3VibGUpTGluZVt5XTsKCQlJbWFnZSArPSBXaWR0aDsKCX0KfQoKLyoqCiBQdXRSb3cKCiBAcGFyYW0gSW1hZ2UgT3V0cHV0IGltYWdlIGFycmF5CiBAcGFyYW0geSB5IGNvb3JkaW5hdGUgb2YgdGhlIHNlbGVjdGVkIGxpbmUKIEBwYXJhbSBMaW5lIElucHV0IGxpbmVhciBhcnJheQogQHBhcmFtIFdpZHRoIGxlbmd0aCBvZiB0aGUgbGluZSBhbmQgd2lkdGggb2YgdGhlIGltYWdlCiovCnN0YXRpYyB2b2lkCQpQdXRSb3coZG91YmxlICpJbWFnZSwgbG9uZyB5LCBkb3VibGUgKkxpbmUsIGxvbmcgV2lkdGgpIHsKCWxvbmcJeDsKCglJbWFnZSA9IEltYWdlICsgKHkgKiBXaWR0aCk7Cglmb3IoeCA9IDBMOyB4IDwgV2lkdGg7IHgrKykgewoJCSpJbWFnZSsrID0gKGRvdWJsZSlMaW5lW3hdOwoJfQp9CgovKioKIFNhbXBsZXNUb0NvZWZmaWNpZW50cy48YnI+CiBJbXBsZW1lbnQgdGhlIGFsZ29yaXRobSB0aGF0IGNvbnZlcnRzIHRoZSBpbWFnZSBzYW1wbGVzIGludG8gQi1zcGxpbmUgY29lZmZpY2llbnRzLiAKIFRoaXMgZWZmaWNpZW50IHByb2NlZHVyZSBlc3NlbnRpYWxseSByZWxpZXMgb24gdGhlIHRocmVlIHBhcGVycyBjaXRlZCBhYm92ZTsgCiBkYXRhIGFyZSBwcm9jZXNzZWQgaW4tcGxhY2UuIAogRXZlbiB0aG91Z2ggdGhpcyBhbGdvcml0aG0gaXMgcm9idXN0IHdpdGggcmVzcGVjdCB0byBxdWFudGl6YXRpb24sIAogd2UgYWR2b2NhdGUgdGhlIHVzZSBvZiBhIGZsb2F0aW5nLXBvaW50IGZvcm1hdCBmb3IgdGhlIGRhdGEuIAoKIEBwYXJhbSBJbWFnZSBJbnB1dCAvIE91dHB1dCBpbWFnZSAoaW4tcGxhY2UgcHJvY2Vzc2luZykKIEBwYXJhbSBXaWR0aCBXaWR0aCBvZiB0aGUgaW1hZ2UKIEBwYXJhbSBIZWlnaHQgSGVpZ2h0IG9mIHRoZSBpbWFnZQogQHBhcmFtIHNwbGluZV9kZWdyZWUgRGVncmVlIG9mIHRoZSBzcGxpbmUgbW9kZWwKIEByZXR1cm4gUmV0dXJucyB0cnVlIGlmIHN1Y2Nlc3MsIGZhbHNlIG90aGVyd2lzZQoqLwpzdGF0aWMgYm9vbAkKU2FtcGxlc1RvQ29lZmZpY2llbnRzKGRvdWJsZSAqSW1hZ2UsIGxvbmcgV2lkdGgsIGxvbmcgSGVpZ2h0LCBsb25nIHNwbGluZV9kZWdyZWUpIHsKCWRvdWJsZQkqTGluZTsKCWRvdWJsZQlQb2xlWzJdOwoJbG9uZwlOYlBvbGVzOwoJbG9uZwl4LCB5OwoKCS8vIHJlY292ZXIgdGhlIHBvbGVzIGZyb20gYSBsb29rdXAgdGFibGUKCXN3aXRjaCAoc3BsaW5lX2RlZ3JlZSkgewoJCWNhc2UgMkw6CgkJCU5iUG9sZXMgPSAxTDsKCQkJUG9sZVswXSA9IHNxcnQoOC4wKSAtIDMuMDsKCQkJYnJlYWs7CgkJY2FzZSAzTDoKCQkJTmJQb2xlcyA9IDFMOwoJCQlQb2xlWzBdID0gc3FydCgzLjApIC0gMi4wOwoJCQlicmVhazsKCQljYXNlIDRMOgoJCQlOYlBvbGVzID0gMkw7CgkJCVBvbGVbMF0gPSBzcXJ0KDY2NC4wIC0gc3FydCg0Mzg5NzYuMCkpICsgc3FydCgzMDQuMCkgLSAxOS4wOwoJCQlQb2xlWzFdID0gc3FydCg2NjQuMCArIHNxcnQoNDM4OTc2LjApKSAtIHNxcnQoMzA0LjApIC0gMTkuMDsKCQkJYnJlYWs7CgkJY2FzZSA1TDoKCQkJTmJQb2xlcyA9IDJMOwoJCQlQb2xlWzBdID0gc3FydCgxMzUuMCAvIDIuMCAtIHNxcnQoMTc3NDUuMCAvIDQuMCkpICsgc3FydCgxMDUuMCAvIDQuMCkKCQkJCS0gMTMuMCAvIDIuMDsKCQkJUG9sZVsxXSA9IHNxcnQoMTM1LjAgLyAyLjAgKyBzcXJ0KDE3NzQ1LjAgLyA0LjApKSAtIHNxcnQoMTA1LjAgLyA0LjApCgkJCQktIDEzLjAgLyAyLjA7CgkJCWJyZWFrOwoJCWRlZmF1bHQ6CgkJCS8vIEludmFsaWQgc3BsaW5lIGRlZ3JlZQoJCQlyZXR1cm4gZmFsc2U7Cgl9CgoJLy8gY29udmVydCB0aGUgaW1hZ2Ugc2FtcGxlcyBpbnRvIGludGVycG9sYXRpb24gY29lZmZpY2llbnRzIAoKCS8vIGluLXBsYWNlIHNlcGFyYWJsZSBwcm9jZXNzLCBhbG9uZyB4IAoJTGluZSA9IChkb3VibGUgKiltYWxsb2MoV2lkdGggKiBzaXplb2YoZG91YmxlKSk7CglpZiAoTGluZSA9PSBOVUxMKSB7CgkJLy8gUm93IGFsbG9jYXRpb24gZmFpbGVkCgkJcmV0dXJuIGZhbHNlOwoJfQoJZm9yICh5ID0gMEw7IHkgPCBIZWlnaHQ7IHkrKykgewoJCUdldFJvdyhJbWFnZSwgeSwgTGluZSwgV2lkdGgpOwoJCUNvbnZlcnRUb0ludGVycG9sYXRpb25Db2VmZmljaWVudHMoTGluZSwgV2lkdGgsIFBvbGUsIE5iUG9sZXMsIERCTF9FUFNJTE9OKTsKCQlQdXRSb3coSW1hZ2UsIHksIExpbmUsIFdpZHRoKTsKCX0KCWZyZWUoTGluZSk7CgoJLy8gaW4tcGxhY2Ugc2VwYXJhYmxlIHByb2Nlc3MsIGFsb25nIHkgCglMaW5lID0gKGRvdWJsZSAqKW1hbGxvYyhIZWlnaHQgKiBzaXplb2YoZG91YmxlKSk7CglpZiAoTGluZSA9PSBOVUxMKSB7CgkJLy8gQ29sdW1uIGFsbG9jYXRpb24gZmFpbGVkCgkJcmV0dXJuIGZhbHNlOwoJfQoJZm9yICh4ID0gMEw7IHggPCBXaWR0aDsgeCsrKSB7CgkJR2V0Q29sdW1uKEltYWdlLCBXaWR0aCwgeCwgTGluZSwgSGVpZ2h0KTsKCQlDb252ZXJ0VG9JbnRlcnBvbGF0aW9uQ29lZmZpY2llbnRzKExpbmUsIEhlaWdodCwgUG9sZSwgTmJQb2xlcywgREJMX0VQU0lMT04pOwoJCVB1dENvbHVtbihJbWFnZSwgV2lkdGgsIHgsIExpbmUsIEhlaWdodCk7Cgl9CglmcmVlKExpbmUpOwoKCXJldHVybiB0cnVlOwp9CgovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vIEludGVycG9sYXRpb24gcm91dGluZXMKCi8qKgpQZXJmb3JtIHRoZSBiaWRpbWVuc2lvbmFsIGludGVycG9sYXRpb24gb2YgYW4gaW1hZ2UuCkdpdmVuIGFuIGFycmF5IG9mIHNwbGluZSBjb2VmZmljaWVudHMsIHJldHVybiB0aGUgdmFsdWUgb2YgCnRoZSB1bmRlcmx5aW5nIGNvbnRpbnVvdXMgc3BsaW5lIG1vZGVsLCBzYW1wbGVkIGF0IHRoZSBsb2NhdGlvbiAoeCwgeSkuIApUaGUgbW9kZWwgZGVncmVlIGNhbiBiZSAyIChxdWFkcmF0aWMpLCAzIChjdWJpYyksIDQgKHF1YXJ0aWMpLCBvciA1IChxdWludGljKS4KCkBwYXJhbSBCY29lZmYgSW5wdXQgQi1zcGxpbmUgYXJyYXkgb2YgY29lZmZpY2llbnRzCkBwYXJhbSBXaWR0aCBXaWR0aCBvZiB0aGUgaW1hZ2UKQHBhcmFtIEhlaWdodCBIZWlnaHQgb2YgdGhlIGltYWdlCkBwYXJhbSB4IHggY29vcmRpbmF0ZSB3aGVyZSB0byBpbnRlcnBvbGF0ZQpAcGFyYW0geSB5IGNvb3JkaW5hdGUgd2hlcmUgdG8gaW50ZXJwb2xhdGUKQHBhcmFtIHNwbGluZV9kZWdyZWUgRGVncmVlIG9mIHRoZSBzcGxpbmUgbW9kZWwKQHJldHVybiBSZXR1cm5zIHRoZSB2YWx1ZSBvZiB0aGUgdW5kZXJseWluZyBjb250aW51b3VzIHNwbGluZSBtb2RlbCwgCnNhbXBsZWQgYXQgdGhlIGxvY2F0aW9uICh4LCB5KQoqLwpzdGF0aWMgZG91YmxlIApJbnRlcnBvbGF0ZWRWYWx1ZShkb3VibGUgKkJjb2VmZiwgbG9uZyBXaWR0aCwgbG9uZyBIZWlnaHQsIGRvdWJsZSB4LCBkb3VibGUgeSwgbG9uZyBzcGxpbmVfZGVncmVlKSB7Cglkb3VibGUJKnA7Cglkb3VibGUJeFdlaWdodFs2XSwgeVdlaWdodFs2XTsKCWRvdWJsZQlpbnRlcnBvbGF0ZWQ7Cglkb3VibGUJdywgdzIsIHc0LCB0LCB0MCwgdDE7Cglsb25nCXhJbmRleFs2XSwgeUluZGV4WzZdOwoJbG9uZwlXaWR0aDIgPSAyTCAqIFdpZHRoIC0gMkwsIEhlaWdodDIgPSAyTCAqIEhlaWdodCAtIDJMOwoJbG9uZwlpLCBqLCBrOwoKCS8vIGNvbXB1dGUgdGhlIGludGVycG9sYXRpb24gaW5kZXhlcwoJaWYgKHNwbGluZV9kZWdyZWUgJiAxTCkgewoJCWkgPSAobG9uZylmbG9vcih4KSAtIHNwbGluZV9kZWdyZWUgLyAyTDsKCQlqID0gKGxvbmcpZmxvb3IoeSkgLSBzcGxpbmVfZGVncmVlIC8gMkw7CgkJZm9yKGsgPSAwOyBrIDw9IHNwbGluZV9kZWdyZWU7IGsrKykgewoJCQl4SW5kZXhba10gPSBpKys7CgkJCXlJbmRleFtrXSA9IGorKzsKCQl9Cgl9CgllbHNlIHsKCQlpID0gKGxvbmcpZmxvb3IoeCArIDAuNSkgLSBzcGxpbmVfZGVncmVlIC8gMkw7CgkJaiA9IChsb25nKWZsb29yKHkgKyAwLjUpIC0gc3BsaW5lX2RlZ3JlZSAvIDJMOwoJCWZvciAoayA9IDA7IGsgPD0gc3BsaW5lX2RlZ3JlZTsgaysrKSB7CgkJCXhJbmRleFtrXSA9IGkrKzsKCQkJeUluZGV4W2tdID0gaisrOwoJCX0KCX0KCgkvLyBjb21wdXRlIHRoZSBpbnRlcnBvbGF0aW9uIHdlaWdodHMKCXN3aXRjaCAoc3BsaW5lX2RlZ3JlZSkgewoJCWNhc2UgMkw6CgkJCS8qIHggKi8KCQkJdyA9IHggLSAoZG91YmxlKXhJbmRleFsxXTsKCQkJeFdlaWdodFsxXSA9IDMuMCAvIDQuMCAtIHcgKiB3OwoJCQl4V2VpZ2h0WzJdID0gKDEuMCAvIDIuMCkgKiAodyAtIHhXZWlnaHRbMV0gKyAxLjApOwoJCQl4V2VpZ2h0WzBdID0gMS4wIC0geFdlaWdodFsxXSAtIHhXZWlnaHRbMl07CgkJCS8qIHkgKi8KCQkJdyA9IHkgLSAoZG91YmxlKXlJbmRleFsxXTsKCQkJeVdlaWdodFsxXSA9IDMuMCAvIDQuMCAtIHcgKiB3OwoJCQl5V2VpZ2h0WzJdID0gKDEuMCAvIDIuMCkgKiAodyAtIHlXZWlnaHRbMV0gKyAxLjApOwoJCQl5V2VpZ2h0WzBdID0gMS4wIC0geVdlaWdodFsxXSAtIHlXZWlnaHRbMl07CgkJCWJyZWFrOwoJCWNhc2UgM0w6CgkJCS8qIHggKi8KCQkJdyA9IHggLSAoZG91YmxlKXhJbmRleFsxXTsKCQkJeFdlaWdodFszXSA9ICgxLjAgLyA2LjApICogdyAqIHcgKiB3OwoJCQl4V2VpZ2h0WzBdID0gKDEuMCAvIDYuMCkgKyAoMS4wIC8gMi4wKSAqIHcgKiAodyAtIDEuMCkgLSB4V2VpZ2h0WzNdOwoJCQl4V2VpZ2h0WzJdID0gdyArIHhXZWlnaHRbMF0gLSAyLjAgKiB4V2VpZ2h0WzNdOwoJCQl4V2VpZ2h0WzFdID0gMS4wIC0geFdlaWdodFswXSAtIHhXZWlnaHRbMl0gLSB4V2VpZ2h0WzNdOwoJCQkvKiB5ICovCgkJCXcgPSB5IC0gKGRvdWJsZSl5SW5kZXhbMV07CgkJCXlXZWlnaHRbM10gPSAoMS4wIC8gNi4wKSAqIHcgKiB3ICogdzsKCQkJeVdlaWdodFswXSA9ICgxLjAgLyA2LjApICsgKDEuMCAvIDIuMCkgKiB3ICogKHcgLSAxLjApIC0geVdlaWdodFszXTsKCQkJeVdlaWdodFsyXSA9IHcgKyB5V2VpZ2h0WzBdIC0gMi4wICogeVdlaWdodFszXTsKCQkJeVdlaWdodFsxXSA9IDEuMCAtIHlXZWlnaHRbMF0gLSB5V2VpZ2h0WzJdIC0geVdlaWdodFszXTsKCQkJYnJlYWs7CgkJY2FzZSA0TDoKCQkJLyogeCAqLwoJCQl3ID0geCAtIChkb3VibGUpeEluZGV4WzJdOwoJCQl3MiA9IHcgKiB3OwoJCQl0ID0gKDEuMCAvIDYuMCkgKiB3MjsKCQkJeFdlaWdodFswXSA9IDEuMCAvIDIuMCAtIHc7CgkJCXhXZWlnaHRbMF0gKj0geFdlaWdodFswXTsKCQkJeFdlaWdodFswXSAqPSAoMS4wIC8gMjQuMCkgKiB4V2VpZ2h0WzBdOwoJCQl0MCA9IHcgKiAodCAtIDExLjAgLyAyNC4wKTsKCQkJdDEgPSAxOS4wIC8gOTYuMCArIHcyICogKDEuMCAvIDQuMCAtIHQpOwoJCQl4V2VpZ2h0WzFdID0gdDEgKyB0MDsKCQkJeFdlaWdodFszXSA9IHQxIC0gdDA7CgkJCXhXZWlnaHRbNF0gPSB4V2VpZ2h0WzBdICsgdDAgKyAoMS4wIC8gMi4wKSAqIHc7CgkJCXhXZWlnaHRbMl0gPSAxLjAgLSB4V2VpZ2h0WzBdIC0geFdlaWdodFsxXSAtIHhXZWlnaHRbM10gLSB4V2VpZ2h0WzRdOwoJCQkvKiB5ICovCgkJCXcgPSB5IC0gKGRvdWJsZSl5SW5kZXhbMl07CgkJCXcyID0gdyAqIHc7CgkJCXQgPSAoMS4wIC8gNi4wKSAqIHcyOwoJCQl5V2VpZ2h0WzBdID0gMS4wIC8gMi4wIC0gdzsKCQkJeVdlaWdodFswXSAqPSB5V2VpZ2h0WzBdOwoJCQl5V2VpZ2h0WzBdICo9ICgxLjAgLyAyNC4wKSAqIHlXZWlnaHRbMF07CgkJCXQwID0gdyAqICh0IC0gMTEuMCAvIDI0LjApOwoJCQl0MSA9IDE5LjAgLyA5Ni4wICsgdzIgKiAoMS4wIC8gNC4wIC0gdCk7CgkJCXlXZWlnaHRbMV0gPSB0MSArIHQwOwoJCQl5V2VpZ2h0WzNdID0gdDEgLSB0MDsKCQkJeVdlaWdodFs0XSA9IHlXZWlnaHRbMF0gKyB0MCArICgxLjAgLyAyLjApICogdzsKCQkJeVdlaWdodFsyXSA9IDEuMCAtIHlXZWlnaHRbMF0gLSB5V2VpZ2h0WzFdIC0geVdlaWdodFszXSAtIHlXZWlnaHRbNF07CgkJCWJyZWFrOwoJCWNhc2UgNUw6CgkJCS8qIHggKi8KCQkJdyA9IHggLSAoZG91YmxlKXhJbmRleFsyXTsKCQkJdzIgPSB3ICogdzsKCQkJeFdlaWdodFs1XSA9ICgxLjAgLyAxMjAuMCkgKiB3ICogdzIgKiB3MjsKCQkJdzIgLT0gdzsKCQkJdzQgPSB3MiAqIHcyOwoJCQl3IC09IDEuMCAvIDIuMDsKCQkJdCA9IHcyICogKHcyIC0gMy4wKTsKCQkJeFdlaWdodFswXSA9ICgxLjAgLyAyNC4wKSAqICgxLjAgLyA1LjAgKyB3MiArIHc0KSAtIHhXZWlnaHRbNV07CgkJCXQwID0gKDEuMCAvIDI0LjApICogKHcyICogKHcyIC0gNS4wKSArIDQ2LjAgLyA1LjApOwoJCQl0MSA9ICgtMS4wIC8gMTIuMCkgKiB3ICogKHQgKyA0LjApOwoJCQl4V2VpZ2h0WzJdID0gdDAgKyB0MTsKCQkJeFdlaWdodFszXSA9IHQwIC0gdDE7CgkJCXQwID0gKDEuMCAvIDE2LjApICogKDkuMCAvIDUuMCAtIHQpOwoJCQl0MSA9ICgxLjAgLyAyNC4wKSAqIHcgKiAodzQgLSB3MiAtIDUuMCk7CgkJCXhXZWlnaHRbMV0gPSB0MCArIHQxOwoJCQl4V2VpZ2h0WzRdID0gdDAgLSB0MTsKCQkJLyogeSAqLwoJCQl3ID0geSAtIChkb3VibGUpeUluZGV4WzJdOwoJCQl3MiA9IHcgKiB3OwoJCQl5V2VpZ2h0WzVdID0gKDEuMCAvIDEyMC4wKSAqIHcgKiB3MiAqIHcyOwoJCQl3MiAtPSB3OwoJCQl3NCA9IHcyICogdzI7CgkJCXcgLT0gMS4wIC8gMi4wOwoJCQl0ID0gdzIgKiAodzIgLSAzLjApOwoJCQl5V2VpZ2h0WzBdID0gKDEuMCAvIDI0LjApICogKDEuMCAvIDUuMCArIHcyICsgdzQpIC0geVdlaWdodFs1XTsKCQkJdDAgPSAoMS4wIC8gMjQuMCkgKiAodzIgKiAodzIgLSA1LjApICsgNDYuMCAvIDUuMCk7CgkJCXQxID0gKC0xLjAgLyAxMi4wKSAqIHcgKiAodCArIDQuMCk7CgkJCXlXZWlnaHRbMl0gPSB0MCArIHQxOwoJCQl5V2VpZ2h0WzNdID0gdDAgLSB0MTsKCQkJdDAgPSAoMS4wIC8gMTYuMCkgKiAoOS4wIC8gNS4wIC0gdCk7CgkJCXQxID0gKDEuMCAvIDI0LjApICogdyAqICh3NCAtIHcyIC0gNS4wKTsKCQkJeVdlaWdodFsxXSA9IHQwICsgdDE7CgkJCXlXZWlnaHRbNF0gPSB0MCAtIHQxOwoJCQlicmVhazsKCQlkZWZhdWx0OgoJCQkvLyBJbnZhbGlkIHNwbGluZSBkZWdyZWUKCQkJcmV0dXJuIDA7Cgl9CgoJLy8gYXBwbHkgdGhlIG1pcnJvciBib3VuZGFyeSBjb25kaXRpb25zCglmb3IoayA9IDA7IGsgPD0gc3BsaW5lX2RlZ3JlZTsgaysrKSB7CgkJeEluZGV4W2tdID0gKFdpZHRoID09IDFMKSA/ICgwTCkgOiAoKHhJbmRleFtrXSA8IDBMKSA/CgkJCSgteEluZGV4W2tdIC0gV2lkdGgyICogKCgteEluZGV4W2tdKSAvIFdpZHRoMikpCgkJCTogKHhJbmRleFtrXSAtIFdpZHRoMiAqICh4SW5kZXhba10gLyBXaWR0aDIpKSk7CgkJaWYgKFdpZHRoIDw9IHhJbmRleFtrXSkgewoJCQl4SW5kZXhba10gPSBXaWR0aDIgLSB4SW5kZXhba107CgkJfQoJCXlJbmRleFtrXSA9IChIZWlnaHQgPT0gMUwpID8gKDBMKSA6ICgoeUluZGV4W2tdIDwgMEwpID8KCQkJKC15SW5kZXhba10gLSBIZWlnaHQyICogKCgteUluZGV4W2tdKSAvIEhlaWdodDIpKQoJCQk6ICh5SW5kZXhba10gLSBIZWlnaHQyICogKHlJbmRleFtrXSAvIEhlaWdodDIpKSk7CgkJaWYgKEhlaWdodCA8PSB5SW5kZXhba10pIHsKCQkJeUluZGV4W2tdID0gSGVpZ2h0MiAtIHlJbmRleFtrXTsKCQl9Cgl9CgoJLy8gcGVyZm9ybSBpbnRlcnBvbGF0aW9uCglpbnRlcnBvbGF0ZWQgPSAwLjA7Cglmb3IoaiA9IDA7IGogPD0gc3BsaW5lX2RlZ3JlZTsgaisrKSB7CgkJcCA9IEJjb2VmZiArICh5SW5kZXhbal0gKiBXaWR0aCk7CgkJdyA9IDAuMDsKCQlmb3IoaSA9IDA7IGkgPD0gc3BsaW5lX2RlZ3JlZTsgaSsrKSB7CgkJCXcgKz0geFdlaWdodFtpXSAqIHBbeEluZGV4W2ldXTsKCQl9CgkJaW50ZXJwb2xhdGVkICs9IHlXZWlnaHRbal0gKiB3OwoJfQoKCXJldHVybiBpbnRlcnBvbGF0ZWQ7Cn0KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8gRnJlZUltYWdlIGltcGxlbWVudGF0aW9uCgoKLyoqIAogSW1hZ2UgdHJhbnNsYXRpb24gYW5kIHJvdGF0aW9uIHVzaW5nIEItU3BsaW5lcy4KCiBAcGFyYW0gZGliIElucHV0IDgtYml0IGdyZXlzY2FsZSBpbWFnZQogQHBhcmFtIGFuZ2xlIE91dHB1dCBpbWFnZSByb3RhdGlvbiBpbiBkZWdyZWUKIEBwYXJhbSB4X3NoaWZ0IE91dHB1dCBpbWFnZSBob3Jpem9udGFsIHNoaWZ0CiBAcGFyYW0geV9zaGlmdCBPdXRwdXQgaW1hZ2UgdmVydGljYWwgc2hpZnQKIEBwYXJhbSB4X29yaWdpbiBPdXRwdXQgb3JpZ2luIG9mIHRoZSB4LWF4aXMKIEBwYXJhbSB5X29yaWdpbiBPdXRwdXQgb3JpZ2luIG9mIHRoZSB5LWF4aXMKIEBwYXJhbSBzcGxpbmVfZGVncmVlIE91dHB1dCBkZWdyZWUgb2YgdGhlIEItc3BsaW5lIG1vZGVsCiBAcGFyYW0gdXNlX21hc2sgV2hldGhlciBvciBub3QgdG8gbWFzayB0aGUgaW1hZ2UKIEByZXR1cm4gUmV0dXJucyB0aGUgdHJhbnNsYXRlZCAmIHJvdGF0ZWQgZGliIGlmIHN1Y2Nlc3NmdWwsIHJldHVybnMgTlVMTCBvdGhlcndpc2UKKi8Kc3RhdGljIEZJQklUTUFQICogClJvdGF0ZThCaXQoRklCSVRNQVAgKmRpYiwgZG91YmxlIGFuZ2xlLCBkb3VibGUgeF9zaGlmdCwgZG91YmxlIHlfc2hpZnQsIGRvdWJsZSB4X29yaWdpbiwgZG91YmxlIHlfb3JpZ2luLCBsb25nIHNwbGluZV9kZWdyZWUsIEJPT0wgdXNlX21hc2spIHsKCWRvdWJsZQkqSW1hZ2VSYXN0ZXJBcnJheTsKCWRvdWJsZQlwOwoJZG91YmxlCWExMSwgYTEyLCBhMjEsIGEyMjsKCWRvdWJsZQl4MCwgeTAsIHgxLCB5MTsKCWxvbmcJeCwgeTsKCWxvbmcJc3BsaW5lOwoJYm9vbAliUmVzdWx0OwoKCWludCBicHAgPSBGcmVlSW1hZ2VfR2V0QlBQKGRpYik7CglpZihicHAgIT0gOCkgewoJCXJldHVybiBOVUxMOwoJfQoJCglpbnQgd2lkdGggPSBGcmVlSW1hZ2VfR2V0V2lkdGgoZGliKTsKCWludCBoZWlnaHQgPSBGcmVlSW1hZ2VfR2V0SGVpZ2h0KGRpYik7Cglzd2l0Y2goc3BsaW5lX2RlZ3JlZSkgewoJCWNhc2UgUk9UQVRFX1FVQURSQVRJQzoKCQkJc3BsaW5lID0gMkw7CS8vIFVzZSBzcGxpbmVzIG9mIGRlZ3JlZSAyIChxdWFkcmF0aWMgaW50ZXJwb2xhdGlvbikKCQkJYnJlYWs7CgkJY2FzZSBST1RBVEVfQ1VCSUM6CgkJCXNwbGluZSA9IDNMOwkvLyBVc2Ugc3BsaW5lcyBvZiBkZWdyZWUgMyAoY3ViaWMgaW50ZXJwb2xhdGlvbikKCQkJYnJlYWs7CgkJY2FzZSBST1RBVEVfUVVBUlRJQzoKCQkJc3BsaW5lID0gNEw7CS8vIFVzZSBzcGxpbmVzIG9mIGRlZ3JlZSA0IChxdWFydGljIGludGVycG9sYXRpb24pCgkJCWJyZWFrOwoJCWNhc2UgUk9UQVRFX1FVSU5USUM6CgkJCXNwbGluZSA9IDVMOwkvLyBVc2Ugc3BsaW5lcyBvZiBkZWdyZWUgNSAocXVpbnRpYyBpbnRlcnBvbGF0aW9uKQoJCQlicmVhazsKCQlkZWZhdWx0OgoJCQlzcGxpbmUgPSAzTDsKCX0KCgkvLyBhbGxvY2F0ZSBvdXRwdXQgaW1hZ2UKCUZJQklUTUFQICpkc3QgPSBGcmVlSW1hZ2VfQWxsb2NhdGUod2lkdGgsIGhlaWdodCwgYnBwKTsKCWlmKCFkc3QpCgkJcmV0dXJuIE5VTEw7CgkvLyBidWlkIGEgZ3JleSBzY2FsZSBwYWxldHRlCglSR0JRVUFEICpwYWwgPSBGcmVlSW1hZ2VfR2V0UGFsZXR0ZShkc3QpOwoJZm9yKGludCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CgkJcGFsW2ldLnJnYlJlZCA9IHBhbFtpXS5yZ2JHcmVlbiA9IHBhbFtpXS5yZ2JCbHVlID0gKEJZVEUpaTsKCX0KCgkvLyBhbGxvY2F0ZSBhIHRlbXBvcmFyeSBhcnJheQoJSW1hZ2VSYXN0ZXJBcnJheSA9IChkb3VibGUqKW1hbGxvYyh3aWR0aCAqIGhlaWdodCAqIHNpemVvZihkb3VibGUpKTsKCWlmKCFJbWFnZVJhc3RlckFycmF5KSB7CgkJRnJlZUltYWdlX1VubG9hZChkc3QpOwoJCXJldHVybiBOVUxMOwoJfQoJLy8gY29weSBkYXRhIHNhbXBsZXMKCWZvcih5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CgkJZG91YmxlICpwSW1hZ2UgPSAmSW1hZ2VSYXN0ZXJBcnJheVt5KndpZHRoXTsKCQlCWVRFICpzcmNfYml0cyA9IEZyZWVJbWFnZV9HZXRTY2FuTGluZShkaWIsIGhlaWdodC0xLXkpOwoKCQlmb3IoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7CgkJCXBJbWFnZVt4XSA9IChkb3VibGUpc3JjX2JpdHNbeF07CgkJfQoJfQoKCS8vIGNvbnZlcnQgYmV0d2VlbiBhIHJlcHJlc2VudGF0aW9uIGJhc2VkIG9uIGltYWdlIHNhbXBsZXMKCS8vIGFuZCBhIHJlcHJlc2VudGF0aW9uIGJhc2VkIG9uIGltYWdlIEItc3BsaW5lIGNvZWZmaWNpZW50cwoJYlJlc3VsdCA9IFNhbXBsZXNUb0NvZWZmaWNpZW50cyhJbWFnZVJhc3RlckFycmF5LCB3aWR0aCwgaGVpZ2h0LCBzcGxpbmUpOwoJaWYoIWJSZXN1bHQpIHsKCQlGcmVlSW1hZ2VfVW5sb2FkKGRzdCk7CgkJZnJlZShJbWFnZVJhc3RlckFycmF5KTsKCQlyZXR1cm4gTlVMTDsKCX0KCgkvLyBwcmVwYXJlIHRoZSBnZW9tZXRyeQoJYW5nbGUgKj0gUEkgLyAxODAuMDsKCWExMSA9IGNvcyhhbmdsZSk7CglhMTIgPSAtc2luKGFuZ2xlKTsKCWEyMSA9IHNpbihhbmdsZSk7CglhMjIgPSBjb3MoYW5nbGUpOwoJeDAgPSBhMTEgKiAoeF9zaGlmdCArIHhfb3JpZ2luKSArIGExMiAqICh5X3NoaWZ0ICsgeV9vcmlnaW4pOwoJeTAgPSBhMjEgKiAoeF9zaGlmdCArIHhfb3JpZ2luKSArIGEyMiAqICh5X3NoaWZ0ICsgeV9vcmlnaW4pOwoJeF9zaGlmdCA9IHhfb3JpZ2luIC0geDA7Cgl5X3NoaWZ0ID0geV9vcmlnaW4gLSB5MDsKCgkvLyB2aXNpdCBhbGwgcGl4ZWxzIG9mIHRoZSBvdXRwdXQgaW1hZ2UgYW5kIGFzc2lnbiB0aGVpciB2YWx1ZQoJZm9yKHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKCQlCWVRFICpkc3RfYml0cyA9IEZyZWVJbWFnZV9HZXRTY2FuTGluZShkc3QsIGhlaWdodC0xLXkpOwoJCQoJCXgwID0gYTEyICogKGRvdWJsZSl5ICsgeF9zaGlmdDsKCQl5MCA9IGEyMiAqIChkb3VibGUpeSArIHlfc2hpZnQ7CgoJCWZvcih4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKCQkJeDEgPSB4MCArIGExMSAqIChkb3VibGUpeDsKCQkJeTEgPSB5MCArIGEyMSAqIChkb3VibGUpeDsKCQkJaWYodXNlX21hc2spIHsKCQkJCWlmKCh4MSA8PSAtMC41KSB8fCAoKChkb3VibGUpd2lkdGggLSAwLjUpIDw9IHgxKSB8fCAoeTEgPD0gLTAuNSkgfHwgKCgoZG91YmxlKWhlaWdodCAtIDAuNSkgPD0geTEpKSB7CgkJCQkJcCA9IDA7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlwID0gKGRvdWJsZSlJbnRlcnBvbGF0ZWRWYWx1ZShJbWFnZVJhc3RlckFycmF5LCB3aWR0aCwgaGVpZ2h0LCB4MSwgeTEsIHNwbGluZSk7CgkJCQl9CgkJCX0KCQkJZWxzZSB7CgkJCQlwID0gKGRvdWJsZSlJbnRlcnBvbGF0ZWRWYWx1ZShJbWFnZVJhc3RlckFycmF5LCB3aWR0aCwgaGVpZ2h0LCB4MSwgeTEsIHNwbGluZSk7CgkJCX0KCQkJLy8gY2xhbXAgYW5kIGNvbnZlcnQgdG8gQllURQoJCQlkc3RfYml0c1t4XSA9IChCWVRFKU1JTihNQVgoKGludCkwLCAoaW50KShwICsgMC41KSksIChpbnQpMjU1KTsKCQl9Cgl9CgoJLy8gZnJlZSB3b3JraW5nIGFycmF5IGFuZCByZXR1cm4KCWZyZWUoSW1hZ2VSYXN0ZXJBcnJheSk7CgoJcmV0dXJuIGRzdDsKfQoKLyoqIAogSW1hZ2Ugcm90YXRpb24gdXNpbmcgYSAzcmQgb3JkZXIgKGN1YmljKSBCLVNwbGluZXMuCgogQHBhcmFtIGRpYiBJbnB1dCBkaWIgKDgsIDI0IG9yIDMyLWJpdCkKIEBwYXJhbSBhbmdsZSBPdXRwdXQgaW1hZ2Ugcm90YXRpb24KIEBwYXJhbSB4X3NoaWZ0IE91dHB1dCBpbWFnZSBob3Jpem9udGFsIHNoaWZ0CiBAcGFyYW0geV9zaGlmdCBPdXRwdXQgaW1hZ2UgdmVydGljYWwgc2hpZnQKIEBwYXJhbSB4X29yaWdpbiBPdXRwdXQgb3JpZ2luIG9mIHRoZSB4LWF4aXMKIEBwYXJhbSB5X29yaWdpbiBPdXRwdXQgb3JpZ2luIG9mIHRoZSB5LWF4aXMKIEBwYXJhbSB1c2VfbWFzayBXaGV0aGVyIG9yIG5vdCB0byBtYXNrIHRoZSBpbWFnZQogQHJldHVybiBSZXR1cm5zIHRoZSB0cmFuc2xhdGVkICYgcm90YXRlZCBkaWIgaWYgc3VjY2Vzc2Z1bCwgcmV0dXJucyBOVUxMIG90aGVyd2lzZQoqLwpGSUJJVE1BUCAqIERMTF9DQUxMQ09OViAKRnJlZUltYWdlX1JvdGF0ZUV4KEZJQklUTUFQICpkaWIsIGRvdWJsZSBhbmdsZSwgZG91YmxlIHhfc2hpZnQsIGRvdWJsZSB5X3NoaWZ0LCBkb3VibGUgeF9vcmlnaW4sIGRvdWJsZSB5X29yaWdpbiwgQk9PTCB1c2VfbWFzaykgewoKCWludCB4LCB5LCBicHA7CglpbnQgY2hhbm5lbCwgbmJfY2hhbm5lbHM7CglCWVRFICpzcmNfYml0cywgKmRzdF9iaXRzOwoJRklCSVRNQVAgKnNyYzggPSBOVUxMLCAqZHN0OCA9IE5VTEwsICpkc3QgPSBOVUxMOwoKCWlmKCFGcmVlSW1hZ2VfSGFzUGl4ZWxzKGRpYikpIHJldHVybiBOVUxMOwoKCXRyeSB7CgoJCWJwcCA9IEZyZWVJbWFnZV9HZXRCUFAoZGliKTsKCgkJaWYoYnBwID09IDgpIHsKCQkJRklCSVRNQVAgKmRzdF84ID0gUm90YXRlOEJpdChkaWIsIGFuZ2xlLCB4X3NoaWZ0LCB5X3NoaWZ0LCB4X29yaWdpbiwgeV9vcmlnaW4sIFJPVEFURV9DVUJJQywgdXNlX21hc2spOwoJCQlpZihkc3RfOCkgewoJCQkJLy8gY29weSBtZXRhZGF0YSBmcm9tIHNyYyB0byBkc3QKCQkJCUZyZWVJbWFnZV9DbG9uZU1ldGFkYXRhKGRzdF84LCBkaWIpOwoJCQl9CgkJCXJldHVybiBkc3RfODsKCQl9CgkJaWYoKGJwcCA9PSAyNCkgfHwgKGJwcCA9PSAzMikpIHsKCQkJLy8gYWxsb2NhdGUgZHN0IGltYWdlCgkJCWludCB3aWR0aCAgPSBGcmVlSW1hZ2VfR2V0V2lkdGgoZGliKTsKCQkJaW50IGhlaWdodCA9IEZyZWVJbWFnZV9HZXRIZWlnaHQoZGliKTsKCQkJaWYoIGJwcCA9PSAyNCApIHsKCQkJCWRzdCA9IEZyZWVJbWFnZV9BbGxvY2F0ZSh3aWR0aCwgaGVpZ2h0LCBicHAsIEZJX1JHQkFfUkVEX01BU0ssIEZJX1JHQkFfR1JFRU5fTUFTSywgRklfUkdCQV9CTFVFX01BU0spOwoJCQl9IGVsc2UgewoJCQkJZHN0ID0gRnJlZUltYWdlX0FsbG9jYXRlKHdpZHRoLCBoZWlnaHQsIGJwcCwgRklfUkdCQV9SRURfTUFTSywgRklfUkdCQV9HUkVFTl9NQVNLLCBGSV9SR0JBX0JMVUVfTUFTSyk7CgkJCX0KCQkJaWYoIWRzdCkgdGhyb3coMSk7CgoJCQkvLyBhbGxvY2F0ZSBhIHRlbXBvcmFyeSA4LWJpdCBkaWIgKG5vIG5lZWQgdG8gYnVpbGQgYSBwYWxldHRlKQoJCQlzcmM4ID0gRnJlZUltYWdlX0FsbG9jYXRlKHdpZHRoLCBoZWlnaHQsIDgpOwoJCQlpZighc3JjOCkgdGhyb3coMSk7CgoJCQkvLyBwcm9jZXNzIGVhY2ggY2hhbm5lbCBzZXBhcmF0ZWx5CgkJCS8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCQkJbmJfY2hhbm5lbHMgPSAoYnBwIC8gOCk7CgoJCQlmb3IoY2hhbm5lbCA9IDA7IGNoYW5uZWwgPCBuYl9jaGFubmVsczsgY2hhbm5lbCsrKSB7CgkJCQkvLyBleHRyYWN0IGNoYW5uZWwgZnJvbSBzb3VyY2UgZGliCgkJCQlmb3IoeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewoJCQkJCXNyY19iaXRzID0gRnJlZUltYWdlX0dldFNjYW5MaW5lKGRpYiwgeSk7CgkJCQkJZHN0X2JpdHMgPSBGcmVlSW1hZ2VfR2V0U2NhbkxpbmUoc3JjOCwgeSk7CgkJCQkJZm9yKHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewoJCQkJCQlkc3RfYml0c1t4XSA9IHNyY19iaXRzW2NoYW5uZWxdOwoJCQkJCQlzcmNfYml0cyArPSBuYl9jaGFubmVsczsKCQkJCQl9CgkJCQl9CgoJCQkJLy8gcHJvY2VzcyBjaGFubmVsCgkJCQlkc3Q4ID0gUm90YXRlOEJpdChzcmM4LCBhbmdsZSwgeF9zaGlmdCwgeV9zaGlmdCwgeF9vcmlnaW4sIHlfb3JpZ2luLCBST1RBVEVfQ1VCSUMsIHVzZV9tYXNrKTsKCQkJCWlmKCFkc3Q4KSB0aHJvdygxKTsKCgkJCQkvLyBpbnNlcnQgY2hhbm5lbCB0byBkZXN0aW5hdGlvbiBkaWIKCQkJCWZvcih5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CgkJCQkJc3JjX2JpdHMgPSBGcmVlSW1hZ2VfR2V0U2NhbkxpbmUoZHN0OCwgeSk7CgkJCQkJZHN0X2JpdHMgPSBGcmVlSW1hZ2VfR2V0U2NhbkxpbmUoZHN0LCB5KTsKCQkJCQlmb3IoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7CgkJCQkJCWRzdF9iaXRzW2NoYW5uZWxdID0gc3JjX2JpdHNbeF07CgkJCQkJCWRzdF9iaXRzICs9IG5iX2NoYW5uZWxzOwoJCQkJCX0KCQkJCX0KCgkJCQlGcmVlSW1hZ2VfVW5sb2FkKGRzdDgpOwoJCQl9CgoJCQlGcmVlSW1hZ2VfVW5sb2FkKHNyYzgpOwoKCQkJLy8gY29weSBtZXRhZGF0YSBmcm9tIHNyYyB0byBkc3QKCQkJRnJlZUltYWdlX0Nsb25lTWV0YWRhdGEoZHN0LCBkaWIpOwoJCQkKCQkJcmV0dXJuIGRzdDsKCQl9Cgl9IGNhdGNoKGludCkgewoJCWlmKHNyYzgpIEZyZWVJbWFnZV9VbmxvYWQoc3JjOCk7CgkJaWYoZHN0OCkgRnJlZUltYWdlX1VubG9hZChkc3Q4KTsKCQlpZihkc3QpICBGcmVlSW1hZ2VfVW5sb2FkKGRzdCk7Cgl9CgoJcmV0dXJuIE5VTEw7Cn0K