LyoKICogJFhGcmVlODY6ICQKICoKICogQ29weXJpZ2h0IKkgMjAwMCBLZWl0aCBQYWNrYXJkLCBtZW1iZXIgb2YgVGhlIFhGcmVlODYgUHJvamVjdCwgSW5jLgogKgogKiBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlLCBhbmQgc2VsbCB0aGlzIHNvZnR3YXJlIGFuZCBpdHMKICogZG9jdW1lbnRhdGlvbiBmb3IgYW55IHB1cnBvc2UgaXMgaGVyZWJ5IGdyYW50ZWQgd2l0aG91dCBmZWUsIHByb3ZpZGVkIHRoYXQKICogdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYXBwZWFyIGluIGFsbCBjb3BpZXMgYW5kIHRoYXQgYm90aCB0aGF0CiAqIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2UgYXBwZWFyIGluIHN1cHBvcnRpbmcKICogZG9jdW1lbnRhdGlvbiwgYW5kIHRoYXQgdGhlIG5hbWUgb2YgS2VpdGggUGFja2FyZCBub3QgYmUgdXNlZCBpbgogKiBhZHZlcnRpc2luZyBvciBwdWJsaWNpdHkgcGVydGFpbmluZyB0byBkaXN0cmlidXRpb24gb2YgdGhlIHNvZnR3YXJlIHdpdGhvdXQKICogc3BlY2lmaWMsIHdyaXR0ZW4gcHJpb3IgcGVybWlzc2lvbi4gIEtlaXRoIFBhY2thcmQgbWFrZXMgbm8KICogcmVwcmVzZW50YXRpb25zIGFib3V0IHRoZSBzdWl0YWJpbGl0eSBvZiB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZS4gIEl0CiAqIGlzIHByb3ZpZGVkICJhcyBpcyIgd2l0aG91dCBleHByZXNzIG9yIGltcGxpZWQgd2FycmFudHkuCiAqCiAqIEtFSVRIIFBBQ0tBUkQgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEggUkVHQVJEIFRPIFRISVMgU09GVFdBUkUsCiAqIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUywgSU4gTk8KICogRVZFTlQgU0hBTEwgS0VJVEggUEFDS0FSRCBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBJTkRJUkVDVCBPUgogKiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTSBMT1NTIE9GIFVTRSwKICogREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUiBPVEhFUgogKiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SCiAqIFBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuCiAqLwoKI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8Y3R5cGUuaD4KI2luY2x1ZGUgImZjaW50LmgiCiNpbmNsdWRlIDxzdGRpby5oPgoKc3RhdGljIGRvdWJsZQpGY0NvbXBhcmVJbnRlZ2VyIChjaGFyICpvYmplY3QsIEZjVmFsdWUgdmFsdWUxLCBGY1ZhbHVlIHZhbHVlMikKewogICAgaW50CXY7CiAgICAKICAgIGlmICh2YWx1ZTIudHlwZSAhPSBGY1R5cGVJbnRlZ2VyIHx8IHZhbHVlMS50eXBlICE9IEZjVHlwZUludGVnZXIpCglyZXR1cm4gLTEuMDsKICAgIHYgPSB2YWx1ZTIudS5pIC0gdmFsdWUxLnUuaTsKICAgIGlmICh2IDwgMCkKCXYgPSAtdjsKICAgIHJldHVybiAoZG91YmxlKSB2Owp9CgpzdGF0aWMgZG91YmxlCkZjQ29tcGFyZVN0cmluZyAoY2hhciAqb2JqZWN0LCBGY1ZhbHVlIHZhbHVlMSwgRmNWYWx1ZSB2YWx1ZTIpCnsKICAgIGlmICh2YWx1ZTIudHlwZSAhPSBGY1R5cGVTdHJpbmcgfHwgdmFsdWUxLnR5cGUgIT0gRmNUeXBlU3RyaW5nKQoJcmV0dXJuIC0xLjA7CiAgICByZXR1cm4gKGRvdWJsZSkgRmNTdHJDbXBJZ25vcmVDYXNlICh2YWx1ZTEudS5zLCB2YWx1ZTIudS5zKSAhPSAwOwp9CgpzdGF0aWMgZG91YmxlCkZjQ29tcGFyZUJvb2wgKGNoYXIgKm9iamVjdCwgRmNWYWx1ZSB2YWx1ZTEsIEZjVmFsdWUgdmFsdWUyKQp7CiAgICBpZiAodmFsdWUyLnR5cGUgIT0gRmNUeXBlQm9vbCB8fCB2YWx1ZTEudHlwZSAhPSBGY1R5cGVCb29sKQoJcmV0dXJuIC0xLjA7CiAgICByZXR1cm4gKGRvdWJsZSkgdmFsdWUyLnUuYiAhPSB2YWx1ZTEudS5iOwp9CgpzdGF0aWMgZG91YmxlCkZjQ29tcGFyZUNoYXJTZXQgKGNoYXIgKm9iamVjdCwgRmNWYWx1ZSB2YWx1ZTEsIEZjVmFsdWUgdmFsdWUyKQp7CiAgICBpZiAodmFsdWUyLnR5cGUgIT0gRmNUeXBlQ2hhclNldCB8fCB2YWx1ZTEudHlwZSAhPSBGY1R5cGVDaGFyU2V0KQoJcmV0dXJuIC0xLjA7CiAgICByZXR1cm4gKGRvdWJsZSkgRmNDaGFyU2V0U3VidHJhY3RDb3VudCAodmFsdWUxLnUuYywgdmFsdWUyLnUuYyk7Cn0KCnN0YXRpYyBkb3VibGUKRmNDb21wYXJlU2l6ZSAoY2hhciAqb2JqZWN0LCBGY1ZhbHVlIHZhbHVlMSwgRmNWYWx1ZSB2YWx1ZTIpCnsKICAgIGRvdWJsZSAgdjEsIHYyLCB2OwoKICAgIHN3aXRjaCAodmFsdWUxLnR5cGUpIHsKICAgIGNhc2UgRmNUeXBlSW50ZWdlcjoKCXYxID0gdmFsdWUxLnUuaTsKCWJyZWFrOwogICAgY2FzZSBGY1R5cGVEb3VibGU6Cgl2MSA9IHZhbHVlMS51LmQ7CglicmVhazsKICAgIGRlZmF1bHQ6CglyZXR1cm4gLTE7CiAgICB9CiAgICBzd2l0Y2ggKHZhbHVlMi50eXBlKSB7CiAgICBjYXNlIEZjVHlwZUludGVnZXI6Cgl2MiA9IHZhbHVlMi51Lmk7CglicmVhazsKICAgIGNhc2UgRmNUeXBlRG91YmxlOgoJdjIgPSB2YWx1ZTIudS5kOwoJYnJlYWs7CiAgICBkZWZhdWx0OgoJcmV0dXJuIC0xOwogICAgfQogICAgaWYgKHYyID09IDApCglyZXR1cm4gMDsKICAgIHYgPSB2MiAtIHYxOwogICAgaWYgKHYgPCAwKQoJdiA9IC12OwogICAgcmV0dXJuIHY7Cn0KCi8qCiAqIE9yZGVyIGlzIHNpZ25pZmljYW50LCBpdCBkZWZpbmVzIHRoZSBwcmVjZWRlbmNlIG9mCiAqIGVhY2ggdmFsdWUsIGVhcmxpZXIgdmFsdWVzIGFyZSBtb3JlIHNpZ25pZmljYW50IHRoYW4KICogbGF0ZXIgdmFsdWVzCiAqLwpzdGF0aWMgRmNNYXRjaGVyIF9GY01hdGNoZXJzIFtdID0gewogICAgeyBGQ19GT1VORFJZLAlGY0NvbXBhcmVTdHJpbmcsIH0sCiAgICB7IEZDX0NIQVJTRVQsCUZjQ29tcGFyZUNoYXJTZXQgfSwKICAgIHsgRkNfQU5USUFMSUFTLAlGY0NvbXBhcmVCb29sLCB9LAogICAgeyBGQ19MQU5HLAkJRmNDb21wYXJlU3RyaW5nIH0sCiAgICB7IEZDX0ZBTUlMWSwJRmNDb21wYXJlU3RyaW5nLCB9LAogICAgeyBGQ19TUEFDSU5HLAlGY0NvbXBhcmVJbnRlZ2VyLCB9LAogICAgeyBGQ19QSVhFTF9TSVpFLAlGY0NvbXBhcmVTaXplLCB9LAogICAgeyBGQ19TVFlMRSwJCUZjQ29tcGFyZVN0cmluZywgfSwKICAgIHsgRkNfU0xBTlQsCQlGY0NvbXBhcmVJbnRlZ2VyLCB9LAogICAgeyBGQ19XRUlHSFQsCUZjQ29tcGFyZUludGVnZXIsIH0sCiAgICB7IEZDX1JBU1RFUklaRVIsCUZjQ29tcGFyZVN0cmluZywgfSwKICAgIHsgRkNfT1VUTElORSwJRmNDb21wYXJlQm9vbCwgfSwKfTsKCiNkZWZpbmUgTlVNX01BVENIRVIgKHNpemVvZiBfRmNNYXRjaGVycyAvIHNpemVvZiBfRmNNYXRjaGVyc1swXSkKCnN0YXRpYyBGY0Jvb2wKRmNDb21wYXJlVmFsdWVMaXN0IChjb25zdCBjaGFyICAqb2JqZWN0LAoJCSAgICBGY1ZhbHVlTGlzdAkqdjFvcmlnLAkvKiBwYXR0ZXJuICovCgkJICAgIEZjVmFsdWVMaXN0ICp2Mm9yaWcsCS8qIHRhcmdldCAqLwoJCSAgICBGY1ZhbHVlCSpiZXN0VmFsdWUsCgkJICAgIGRvdWJsZQkqdmFsdWUsCgkJICAgIEZjUmVzdWx0CSpyZXN1bHQpCnsKICAgIEZjVmFsdWVMaXN0ICAgICp2MSwgKnYyOwogICAgZG91YmxlICAgIAkgICAgdiwgYmVzdDsKICAgIGludAkJICAgIGo7CiAgICBpbnQJCSAgICBpOwogICAgCiAgICBmb3IgKGkgPSAwOyBpIDwgTlVNX01BVENIRVI7IGkrKykKICAgIHsKCWlmICghRmNTdHJDbXBJZ25vcmVDYXNlIChfRmNNYXRjaGVyc1tpXS5vYmplY3QsIG9iamVjdCkpCgkgICAgYnJlYWs7CiAgICB9CiAgICBpZiAoaSA9PSBOVU1fTUFUQ0hFUikKICAgIHsKCWlmIChiZXN0VmFsdWUpCgkgICAgKmJlc3RWYWx1ZSA9IHYyb3JpZy0+dmFsdWU7CglyZXR1cm4gRmNUcnVlOwogICAgfQogICAgCiAgICBiZXN0ID0gMWU5OTsKICAgIGogPSAwOwogICAgZm9yICh2MSA9IHYxb3JpZzsgdjE7IHYxID0gdjEtPm5leHQpCiAgICB7Cglmb3IgKHYyID0gdjJvcmlnOyB2MjsgdjIgPSB2Mi0+bmV4dCkKCXsKCSAgICB2ID0gKCpfRmNNYXRjaGVyc1tpXS5jb21wYXJlKSAoX0ZjTWF0Y2hlcnNbaV0ub2JqZWN0LAoJCQkJCSAgICB2MS0+dmFsdWUsCgkJCQkJICAgIHYyLT52YWx1ZSk7CgkgICAgaWYgKHYgPCAwKQoJICAgIHsKCQkqcmVzdWx0ID0gRmNSZXN1bHRUeXBlTWlzbWF0Y2g7CgkJcmV0dXJuIEZjRmFsc2U7CgkgICAgfQoJICAgIGlmIChGY0RlYnVnICgpICYgRkNfREJHX01BVENIVikKCQlwcmludGYgKCIgdiAlZyBqICVkICIsIHYsIGopOwoJICAgIHYgPSB2ICogMTAwICsgajsKCSAgICBpZiAodiA8IGJlc3QpCgkgICAgewoJCWlmIChiZXN0VmFsdWUpCgkJICAgICpiZXN0VmFsdWUgPSB2Mi0+dmFsdWU7CgkJYmVzdCA9IHY7CgkgICAgfQoJfQoJaisrOwogICAgfQogICAgaWYgKEZjRGVidWcgKCkgJiBGQ19EQkdfTUFUQ0hWKQogICAgewoJcHJpbnRmICgiICVzOiAlZyAiLCBvYmplY3QsIGJlc3QpOwoJRmNWYWx1ZUxpc3RQcmludCAodjFvcmlnKTsKCXByaW50ZiAoIiwgIik7CglGY1ZhbHVlTGlzdFByaW50ICh2Mm9yaWcpOwoJcHJpbnRmICgiXG4iKTsKICAgIH0KICAgIHZhbHVlW2ldICs9IGJlc3Q7CiAgICByZXR1cm4gRmNUcnVlOwp9CgovKgogKiBSZXR1cm4gYSB2YWx1ZSBpbmRpY2F0aW5nIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSB0d28gbGlzdHMgb2YKICogdmFsdWVzCiAqLwoKc3RhdGljIEZjQm9vbApGY0NvbXBhcmUgKEZjUGF0dGVybgkqcGF0LAoJICAgRmNQYXR0ZXJuCSpmbnQsCgkgICBkb3VibGUJKnZhbHVlLAoJICAgRmNSZXN1bHQJKnJlc3VsdCkKewogICAgaW50CQkgICAgaSwgaTEsIGkyOwogICAgCiAgICBmb3IgKGkgPSAwOyBpIDwgTlVNX01BVENIRVI7IGkrKykKCXZhbHVlW2ldID0gMC4wOwogICAgCiAgICBmb3IgKGkxID0gMDsgaTEgPCBwYXQtPm51bTsgaTErKykKICAgIHsKCWZvciAoaTIgPSAwOyBpMiA8IGZudC0+bnVtOyBpMisrKQoJewoJICAgIGlmICghRmNTdHJDbXBJZ25vcmVDYXNlIChwYXQtPmVsdHNbaTFdLm9iamVjdCwKCQkJCSAgICAgZm50LT5lbHRzW2kyXS5vYmplY3QpKQoJICAgIHsKCQlpZiAoIUZjQ29tcGFyZVZhbHVlTGlzdCAocGF0LT5lbHRzW2kxXS5vYmplY3QsCgkJCQkJIHBhdC0+ZWx0c1tpMV0udmFsdWVzLAoJCQkJCSBmbnQtPmVsdHNbaTJdLnZhbHVlcywKCQkJCQkgMCwKCQkJCQkgdmFsdWUsCgkJCQkJIHJlc3VsdCkpCgkJICAgIHJldHVybiBGY0ZhbHNlOwoJCWJyZWFrOwoJICAgIH0KCX0KI2lmIDAKCS8qCgkgKiBPdmVyc3BlY2lmaWVkIHBhdHRlcm5zIGFyZSBzbGlnaHRseSBwZW5hbGl6ZWQgaW4KCSAqIGNhc2Ugc29tZSBvdGhlciBmb250IGluY2x1ZGVzIHRoZSByZXF1ZXN0ZWQgZmllbGQKCSAqLwoJaWYgKGkyID09IGZudC0+bnVtKQoJewoJICAgIGZvciAoaTIgPSAwOyBpMiA8IE5VTV9NQVRDSEVSOyBpMisrKQoJICAgIHsKCQlpZiAoIUZjU3RyQ21wSWdub3JlQ2FzZSAoX0ZjTWF0Y2hlcnNbaTJdLm9iamVjdCwKCQkJCQkgcGF0LT5lbHRzW2kxXS5vYmplY3QpKQoJCXsKCQkgICAgdmFsdWVbaTJdID0gMS4wOwoJCSAgICBicmVhazsKCQl9CgkgICAgfQoJfQojZW5kaWYKICAgIH0KICAgIHJldHVybiBGY1RydWU7Cn0KCkZjUGF0dGVybiAqCkZjRm9udE1hdGNoIChGY0NvbmZpZwkqY29uZmlnLAoJICAgICBGY1BhdHRlcm4JKnAsIAoJICAgICBGY1Jlc3VsdAkqcmVzdWx0KQp7CiAgICBkb3VibGUgICAgCSAgICBzY29yZVtOVU1fTUFUQ0hFUl0sIGJlc3RzY29yZVtOVU1fTUFUQ0hFUl07CiAgICBpbnQJCSAgICBmOwogICAgRmNGb250U2V0CSAgICAqczsKICAgIEZjUGF0dGVybgkgICAgKmJlc3Q7CiAgICBGY1BhdHRlcm4JICAgICpuZXc7CiAgICBGY1BhdHRlcm5FbHQgICAqZmUsICpwZTsKICAgIEZjVmFsdWUJICAgIHY7CiAgICBpbnQJCSAgICBpOwogICAgRmNTZXROYW1lCSAgICBzZXQ7CgogICAgZm9yIChpID0gMDsgaSA8IE5VTV9NQVRDSEVSOyBpKyspCgliZXN0c2NvcmVbaV0gPSAwOwogICAgYmVzdCA9IDA7CiAgICBpZiAoRmNEZWJ1ZyAoKSAmIEZDX0RCR19NQVRDSCkKICAgIHsKCXByaW50ZiAoIk1hdGNoICIpOwoJRmNQYXR0ZXJuUHJpbnQgKHApOwogICAgfQogICAgaWYgKCFjb25maWcpCiAgICB7Cgljb25maWcgPSBGY0NvbmZpZ0dldEN1cnJlbnQgKCk7CglpZiAoIWNvbmZpZykKCSAgICByZXR1cm4gMDsKICAgIH0KICAgIGZvciAoc2V0ID0gRmNTZXRTeXN0ZW07IHNldCA8PSBGY1NldEFwcGxpY2F0aW9uOyBzZXQrKykKICAgIHsKCXMgPSBjb25maWctPmZvbnRzW3NldF07CglpZiAoIXMpCgkgICAgY29udGludWU7Cglmb3IgKGYgPSAwOyBmIDwgcy0+bmZvbnQ7IGYrKykKCXsKCSAgICBpZiAoRmNEZWJ1ZyAoKSAmIEZDX0RCR19NQVRDSFYpCgkgICAgewoJCXByaW50ZiAoIkZvbnQgJWQgIiwgZik7CgkJRmNQYXR0ZXJuUHJpbnQgKHMtPmZvbnRzW2ZdKTsKCSAgICB9CgkgICAgaWYgKCFGY0NvbXBhcmUgKHAsIHMtPmZvbnRzW2ZdLCBzY29yZSwgcmVzdWx0KSkKCQlyZXR1cm4gMDsKCSAgICBpZiAoRmNEZWJ1ZyAoKSAmIEZDX0RCR19NQVRDSFYpCgkgICAgewoJCXByaW50ZiAoIlNjb3JlIik7CgkJZm9yIChpID0gMDsgaSA8IE5VTV9NQVRDSEVSOyBpKyspCgkJewoJCSAgICBwcmludGYgKCIgJWciLCBzY29yZVtpXSk7CgkJfQoJCXByaW50ZiAoIlxuIik7CgkgICAgfQoJICAgIGZvciAoaSA9IDA7IGkgPCBOVU1fTUFUQ0hFUjsgaSsrKQoJICAgIHsKCQlpZiAoYmVzdCAmJiBiZXN0c2NvcmVbaV0gPCBzY29yZVtpXSkKCQkgICAgYnJlYWs7CgkJaWYgKCFiZXN0IHx8IHNjb3JlW2ldIDwgYmVzdHNjb3JlW2ldKQoJCXsKCQkgICAgZm9yIChpID0gMDsgaSA8IE5VTV9NQVRDSEVSOyBpKyspCgkJCWJlc3RzY29yZVtpXSA9IHNjb3JlW2ldOwoJCSAgICBiZXN0ID0gcy0+Zm9udHNbZl07CgkJICAgIGJyZWFrOwoJCX0KCSAgICB9Cgl9CiAgICB9CiAgICBpZiAoRmNEZWJ1ZyAoKSAmIEZDX0RCR19NQVRDSCkKICAgIHsKCXByaW50ZiAoIkJlc3Qgc2NvcmUiKTsKCWZvciAoaSA9IDA7IGkgPCBOVU1fTUFUQ0hFUjsgaSsrKQoJICAgIHByaW50ZiAoIiAlZyIsIGJlc3RzY29yZVtpXSk7CglGY1BhdHRlcm5QcmludCAoYmVzdCk7CiAgICB9CiAgICBpZiAoIWJlc3QpCiAgICB7CgkqcmVzdWx0ID0gRmNSZXN1bHROb01hdGNoOwoJcmV0dXJuIDA7CiAgICB9CiAgICBuZXcgPSBGY1BhdHRlcm5DcmVhdGUgKCk7CiAgICBpZiAoIW5ldykKCXJldHVybiAwOwogICAgZm9yIChpID0gMDsgaSA8IGJlc3QtPm51bTsgaSsrKQogICAgewoJZmUgPSAmYmVzdC0+ZWx0c1tpXTsKCXBlID0gRmNQYXR0ZXJuRmluZCAocCwgZmUtPm9iamVjdCwgRmNGYWxzZSk7CglpZiAocGUpCgl7CgkgICAgaWYgKCFGY0NvbXBhcmVWYWx1ZUxpc3QgKHBlLT5vYmplY3QsIHBlLT52YWx1ZXMsIAoJCQkJICAgICBmZS0+dmFsdWVzLCAmdiwgc2NvcmUsIHJlc3VsdCkpCgkgICAgewoJCUZjUGF0dGVybkRlc3Ryb3kgKG5ldyk7CgkJcmV0dXJuIDA7CgkgICAgfQoJfQoJZWxzZQoJICAgIHYgPSBmZS0+dmFsdWVzLT52YWx1ZTsKCUZjUGF0dGVybkFkZCAobmV3LCBmZS0+b2JqZWN0LCB2LCBGY1RydWUpOwogICAgfQogICAgZm9yIChpID0gMDsgaSA8IHAtPm51bTsgaSsrKQogICAgewoJcGUgPSAmcC0+ZWx0c1tpXTsKCWZlID0gRmNQYXR0ZXJuRmluZCAoYmVzdCwgcGUtPm9iamVjdCwgRmNGYWxzZSk7CglpZiAoIWZlKQoJICAgIEZjUGF0dGVybkFkZCAobmV3LCBwZS0+b2JqZWN0LCBwZS0+dmFsdWVzLT52YWx1ZSwgRmNUcnVlKTsKICAgIH0KICAgIEZjQ29uZmlnU3Vic3RpdHV0ZSAoY29uZmlnLCBuZXcsIEZjTWF0Y2hGb250KTsKICAgIHJldHVybiBuZXc7Cn0K