LyoKICogJFhGcmVlODY6ICQKICoKICogQ29weXJpZ2h0IKkgMjAwMCBLZWl0aCBQYWNrYXJkLCBtZW1iZXIgb2YgVGhlIFhGcmVlODYgUHJvamVjdCwgSW5jLgogKgogKiBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlLCBhbmQgc2VsbCB0aGlzIHNvZnR3YXJlIGFuZCBpdHMKICogZG9jdW1lbnRhdGlvbiBmb3IgYW55IHB1cnBvc2UgaXMgaGVyZWJ5IGdyYW50ZWQgd2l0aG91dCBmZWUsIHByb3ZpZGVkIHRoYXQKICogdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYXBwZWFyIGluIGFsbCBjb3BpZXMgYW5kIHRoYXQgYm90aCB0aGF0CiAqIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2UgYXBwZWFyIGluIHN1cHBvcnRpbmcKICogZG9jdW1lbnRhdGlvbiwgYW5kIHRoYXQgdGhlIG5hbWUgb2YgS2VpdGggUGFja2FyZCBub3QgYmUgdXNlZCBpbgogKiBhZHZlcnRpc2luZyBvciBwdWJsaWNpdHkgcGVydGFpbmluZyB0byBkaXN0cmlidXRpb24gb2YgdGhlIHNvZnR3YXJlIHdpdGhvdXQKICogc3BlY2lmaWMsIHdyaXR0ZW4gcHJpb3IgcGVybWlzc2lvbi4gIEtlaXRoIFBhY2thcmQgbWFrZXMgbm8KICogcmVwcmVzZW50YXRpb25zIGFib3V0IHRoZSBzdWl0YWJpbGl0eSBvZiB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZS4gIEl0CiAqIGlzIHByb3ZpZGVkICJhcyBpcyIgd2l0aG91dCBleHByZXNzIG9yIGltcGxpZWQgd2FycmFudHkuCiAqCiAqIEtFSVRIIFBBQ0tBUkQgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEggUkVHQVJEIFRPIFRISVMgU09GVFdBUkUsCiAqIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUywgSU4gTk8KICogRVZFTlQgU0hBTEwgS0VJVEggUEFDS0FSRCBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBJTkRJUkVDVCBPUgogKiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTSBMT1NTIE9GIFVTRSwKICogREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUiBPVEhFUgogKiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SCiAqIFBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuCiAqLwoKI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8Y3R5cGUuaD4KI2luY2x1ZGUgImZjaW50LmgiCiNpbmNsdWRlIDxzdGRpby5oPgoKc3RhdGljIGRvdWJsZQpGY0NvbXBhcmVJbnRlZ2VyIChjaGFyICpvYmplY3QsIEZjVmFsdWUgdmFsdWUxLCBGY1ZhbHVlIHZhbHVlMikKewogICAgaW50CXY7CiAgICAKICAgIGlmICh2YWx1ZTIudHlwZSAhPSBGY1R5cGVJbnRlZ2VyIHx8IHZhbHVlMS50eXBlICE9IEZjVHlwZUludGVnZXIpCglyZXR1cm4gLTEuMDsKICAgIHYgPSB2YWx1ZTIudS5pIC0gdmFsdWUxLnUuaTsKICAgIGlmICh2IDwgMCkKCXYgPSAtdjsKICAgIHJldHVybiAoZG91YmxlKSB2Owp9CgpzdGF0aWMgZG91YmxlCkZjQ29tcGFyZVN0cmluZyAoY2hhciAqb2JqZWN0LCBGY1ZhbHVlIHZhbHVlMSwgRmNWYWx1ZSB2YWx1ZTIpCnsKICAgIGlmICh2YWx1ZTIudHlwZSAhPSBGY1R5cGVTdHJpbmcgfHwgdmFsdWUxLnR5cGUgIT0gRmNUeXBlU3RyaW5nKQoJcmV0dXJuIC0xLjA7CiAgICByZXR1cm4gKGRvdWJsZSkgRmNTdHJDbXBJZ25vcmVDYXNlICh2YWx1ZTEudS5zLCB2YWx1ZTIudS5zKSAhPSAwOwp9CgpzdGF0aWMgZG91YmxlCkZjQ29tcGFyZUJvb2wgKGNoYXIgKm9iamVjdCwgRmNWYWx1ZSB2YWx1ZTEsIEZjVmFsdWUgdmFsdWUyKQp7CiAgICBpZiAodmFsdWUyLnR5cGUgIT0gRmNUeXBlQm9vbCB8fCB2YWx1ZTEudHlwZSAhPSBGY1R5cGVCb29sKQoJcmV0dXJuIC0xLjA7CiAgICByZXR1cm4gKGRvdWJsZSkgdmFsdWUyLnUuYiAhPSB2YWx1ZTEudS5iOwp9CgpzdGF0aWMgZG91YmxlCkZjQ29tcGFyZUNoYXJTZXQgKGNoYXIgKm9iamVjdCwgRmNWYWx1ZSB2YWx1ZTEsIEZjVmFsdWUgdmFsdWUyKQp7CiAgICBpZiAodmFsdWUyLnR5cGUgIT0gRmNUeXBlQ2hhclNldCB8fCB2YWx1ZTEudHlwZSAhPSBGY1R5cGVDaGFyU2V0KQoJcmV0dXJuIC0xLjA7CiAgICByZXR1cm4gKGRvdWJsZSkgRmNDaGFyU2V0U3VidHJhY3RDb3VudCAodmFsdWUxLnUuYywgdmFsdWUyLnUuYyk7Cn0KCnN0YXRpYyBkb3VibGUKRmNDb21wYXJlU2l6ZSAoY2hhciAqb2JqZWN0LCBGY1ZhbHVlIHZhbHVlMSwgRmNWYWx1ZSB2YWx1ZTIpCnsKICAgIGRvdWJsZSAgdjEsIHYyLCB2OwoKICAgIHN3aXRjaCAodmFsdWUxLnR5cGUpIHsKICAgIGNhc2UgRmNUeXBlSW50ZWdlcjoKCXYxID0gdmFsdWUxLnUuaTsKCWJyZWFrOwogICAgY2FzZSBGY1R5cGVEb3VibGU6Cgl2MSA9IHZhbHVlMS51LmQ7CglicmVhazsKICAgIGRlZmF1bHQ6CglyZXR1cm4gLTE7CiAgICB9CiAgICBzd2l0Y2ggKHZhbHVlMi50eXBlKSB7CiAgICBjYXNlIEZjVHlwZUludGVnZXI6Cgl2MiA9IHZhbHVlMi51Lmk7CglicmVhazsKICAgIGNhc2UgRmNUeXBlRG91YmxlOgoJdjIgPSB2YWx1ZTIudS5kOwoJYnJlYWs7CiAgICBkZWZhdWx0OgoJcmV0dXJuIC0xOwogICAgfQogICAgaWYgKHYyID09IDApCglyZXR1cm4gMDsKICAgIHYgPSB2MiAtIHYxOwogICAgaWYgKHYgPCAwKQoJdiA9IC12OwogICAgcmV0dXJuIHY7Cn0KCi8qCiAqIE9yZGVyIGlzIHNpZ25pZmljYW50LCBpdCBkZWZpbmVzIHRoZSBwcmVjZWRlbmNlIG9mCiAqIGVhY2ggdmFsdWUsIGVhcmxpZXIgdmFsdWVzIGFyZSBtb3JlIHNpZ25pZmljYW50IHRoYW4KICogbGF0ZXIgdmFsdWVzCiAqLwpzdGF0aWMgRmNNYXRjaGVyIF9GY01hdGNoZXJzIFtdID0gewogICAgeyBGQ19GT1VORFJZLAlGY0NvbXBhcmVTdHJpbmcsIH0sCiAgICB7IEZDX0NIQVJTRVQsCUZjQ29tcGFyZUNoYXJTZXQgfSwKICAgIHsgRkNfQU5USUFMSUFTLAlGY0NvbXBhcmVCb29sLCB9LAogICAgeyBGQ19MQU5HLAkJRmNDb21wYXJlU3RyaW5nIH0sCiAgICB7IEZDX0ZBTUlMWSwJRmNDb21wYXJlU3RyaW5nLCB9LAogICAgeyBGQ19TUEFDSU5HLAlGY0NvbXBhcmVJbnRlZ2VyLCB9LAogICAgeyBGQ19QSVhFTF9TSVpFLAlGY0NvbXBhcmVTaXplLCB9LAogICAgeyBGQ19TVFlMRSwJCUZjQ29tcGFyZVN0cmluZywgfSwKICAgIHsgRkNfU0xBTlQsCQlGY0NvbXBhcmVJbnRlZ2VyLCB9LAogICAgeyBGQ19XRUlHSFQsCUZjQ29tcGFyZUludGVnZXIsIH0sCiAgICB7IEZDX1JBU1RFUklaRVIsCUZjQ29tcGFyZVN0cmluZywgfSwKICAgIHsgRkNfT1VUTElORSwJRmNDb21wYXJlQm9vbCwgfSwKfTsKCiNkZWZpbmUgTlVNX01BVENIRVIgKHNpemVvZiBfRmNNYXRjaGVycyAvIHNpemVvZiBfRmNNYXRjaGVyc1swXSkKCnN0YXRpYyBGY0Jvb2wKRmNDb21wYXJlVmFsdWVMaXN0IChjb25zdCBjaGFyICAqb2JqZWN0LAoJCSAgICBGY1ZhbHVlTGlzdAkqdjFvcmlnLAkvKiBwYXR0ZXJuICovCgkJICAgIEZjVmFsdWVMaXN0ICp2Mm9yaWcsCS8qIHRhcmdldCAqLwoJCSAgICBGY1ZhbHVlCSpiZXN0VmFsdWUsCgkJICAgIGRvdWJsZQkqdmFsdWUsCgkJICAgIEZjUmVzdWx0CSpyZXN1bHQpCnsKICAgIEZjVmFsdWVMaXN0ICAgICp2MSwgKnYyOwogICAgZG91YmxlICAgIAkgICAgdiwgYmVzdDsKICAgIGludAkJICAgIGo7CiAgICBpbnQJCSAgICBpOwogICAgCiAgICBmb3IgKGkgPSAwOyBpIDwgTlVNX01BVENIRVI7IGkrKykKICAgIHsKCWlmICghRmNTdHJDbXBJZ25vcmVDYXNlICgoRmNDaGFyOCAqKSBfRmNNYXRjaGVyc1tpXS5vYmplY3QsCgkJCQkgKEZjQ2hhcjggKikgb2JqZWN0KSkKCSAgICBicmVhazsKICAgIH0KICAgIGlmIChpID09IE5VTV9NQVRDSEVSKQogICAgewoJaWYgKGJlc3RWYWx1ZSkKCSAgICAqYmVzdFZhbHVlID0gdjJvcmlnLT52YWx1ZTsKCXJldHVybiBGY1RydWU7CiAgICB9CiAgICAKICAgIGJlc3QgPSAxZTk5OwogICAgaiA9IDA7CiAgICBmb3IgKHYxID0gdjFvcmlnOyB2MTsgdjEgPSB2MS0+bmV4dCkKICAgIHsKCWZvciAodjIgPSB2Mm9yaWc7IHYyOyB2MiA9IHYyLT5uZXh0KQoJewoJICAgIHYgPSAoKl9GY01hdGNoZXJzW2ldLmNvbXBhcmUpIChfRmNNYXRjaGVyc1tpXS5vYmplY3QsCgkJCQkJICAgIHYxLT52YWx1ZSwKCQkJCQkgICAgdjItPnZhbHVlKTsKCSAgICBpZiAodiA8IDApCgkgICAgewoJCSpyZXN1bHQgPSBGY1Jlc3VsdFR5cGVNaXNtYXRjaDsKCQlyZXR1cm4gRmNGYWxzZTsKCSAgICB9CgkgICAgaWYgKEZjRGVidWcgKCkgJiBGQ19EQkdfTUFUQ0hWKQoJCXByaW50ZiAoIiB2ICVnIGogJWQgIiwgdiwgaik7CgkgICAgdiA9IHYgKiAxMDAgKyBqOwoJICAgIGlmICh2IDwgYmVzdCkKCSAgICB7CgkJaWYgKGJlc3RWYWx1ZSkKCQkgICAgKmJlc3RWYWx1ZSA9IHYyLT52YWx1ZTsKCQliZXN0ID0gdjsKCSAgICB9Cgl9CglqKys7CiAgICB9CiAgICBpZiAoRmNEZWJ1ZyAoKSAmIEZDX0RCR19NQVRDSFYpCiAgICB7CglwcmludGYgKCIgJXM6ICVnICIsIG9iamVjdCwgYmVzdCk7CglGY1ZhbHVlTGlzdFByaW50ICh2MW9yaWcpOwoJcHJpbnRmICgiLCAiKTsKCUZjVmFsdWVMaXN0UHJpbnQgKHYyb3JpZyk7CglwcmludGYgKCJcbiIpOwogICAgfQogICAgdmFsdWVbaV0gKz0gYmVzdDsKICAgIHJldHVybiBGY1RydWU7Cn0KCi8qCiAqIFJldHVybiBhIHZhbHVlIGluZGljYXRpbmcgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlIHR3byBsaXN0cyBvZgogKiB2YWx1ZXMKICovCgpzdGF0aWMgRmNCb29sCkZjQ29tcGFyZSAoRmNQYXR0ZXJuCSpwYXQsCgkgICBGY1BhdHRlcm4JKmZudCwKCSAgIGRvdWJsZQkqdmFsdWUsCgkgICBGY1Jlc3VsdAkqcmVzdWx0KQp7CiAgICBpbnQJCSAgICBpLCBpMSwgaTI7CiAgICAKICAgIGZvciAoaSA9IDA7IGkgPCBOVU1fTUFUQ0hFUjsgaSsrKQoJdmFsdWVbaV0gPSAwLjA7CiAgICAKICAgIGZvciAoaTEgPSAwOyBpMSA8IHBhdC0+bnVtOyBpMSsrKQogICAgewoJZm9yIChpMiA9IDA7IGkyIDwgZm50LT5udW07IGkyKyspCgl7CgkgICAgaWYgKCFGY1N0ckNtcElnbm9yZUNhc2UgKChGY0NoYXI4ICopIHBhdC0+ZWx0c1tpMV0ub2JqZWN0LAoJCQkJICAgICAoRmNDaGFyOCAqKSBmbnQtPmVsdHNbaTJdLm9iamVjdCkpCgkgICAgewoJCWlmICghRmNDb21wYXJlVmFsdWVMaXN0IChwYXQtPmVsdHNbaTFdLm9iamVjdCwKCQkJCQkgcGF0LT5lbHRzW2kxXS52YWx1ZXMsCgkJCQkJIGZudC0+ZWx0c1tpMl0udmFsdWVzLAoJCQkJCSAwLAoJCQkJCSB2YWx1ZSwKCQkJCQkgcmVzdWx0KSkKCQkgICAgcmV0dXJuIEZjRmFsc2U7CgkJYnJlYWs7CgkgICAgfQoJfQojaWYgMAoJLyoKCSAqIE92ZXJzcGVjaWZpZWQgcGF0dGVybnMgYXJlIHNsaWdodGx5IHBlbmFsaXplZCBpbgoJICogY2FzZSBzb21lIG90aGVyIGZvbnQgaW5jbHVkZXMgdGhlIHJlcXVlc3RlZCBmaWVsZAoJICovCglpZiAoaTIgPT0gZm50LT5udW0pCgl7CgkgICAgZm9yIChpMiA9IDA7IGkyIDwgTlVNX01BVENIRVI7IGkyKyspCgkgICAgewoJCWlmICghRmNTdHJDbXBJZ25vcmVDYXNlIChfRmNNYXRjaGVyc1tpMl0ub2JqZWN0LAoJCQkJCSBwYXQtPmVsdHNbaTFdLm9iamVjdCkpCgkJewoJCSAgICB2YWx1ZVtpMl0gPSAxLjA7CgkJICAgIGJyZWFrOwoJCX0KCSAgICB9Cgl9CiNlbmRpZgogICAgfQogICAgcmV0dXJuIEZjVHJ1ZTsKfQoKRmNQYXR0ZXJuICoKRmNGb250TWF0Y2ggKEZjQ29uZmlnCSpjb25maWcsCgkgICAgIEZjUGF0dGVybgkqcCwgCgkgICAgIEZjUmVzdWx0CSpyZXN1bHQpCnsKICAgIGRvdWJsZSAgICAJICAgIHNjb3JlW05VTV9NQVRDSEVSXSwgYmVzdHNjb3JlW05VTV9NQVRDSEVSXTsKICAgIGludAkJICAgIGY7CiAgICBGY0ZvbnRTZXQJICAgICpzOwogICAgRmNQYXR0ZXJuCSAgICAqYmVzdDsKICAgIEZjUGF0dGVybgkgICAgKm5ldzsKICAgIEZjUGF0dGVybkVsdCAgICpmZSwgKnBlOwogICAgRmNWYWx1ZQkgICAgdjsKICAgIGludAkJICAgIGk7CiAgICBGY1NldE5hbWUJICAgIHNldDsKCiAgICBmb3IgKGkgPSAwOyBpIDwgTlVNX01BVENIRVI7IGkrKykKCWJlc3RzY29yZVtpXSA9IDA7CiAgICBiZXN0ID0gMDsKICAgIGlmIChGY0RlYnVnICgpICYgRkNfREJHX01BVENIKQogICAgewoJcHJpbnRmICgiTWF0Y2ggIik7CglGY1BhdHRlcm5QcmludCAocCk7CiAgICB9CiAgICBpZiAoIWNvbmZpZykKICAgIHsKCWNvbmZpZyA9IEZjQ29uZmlnR2V0Q3VycmVudCAoKTsKCWlmICghY29uZmlnKQoJICAgIHJldHVybiAwOwogICAgfQogICAgZm9yIChzZXQgPSBGY1NldFN5c3RlbTsgc2V0IDw9IEZjU2V0QXBwbGljYXRpb247IHNldCsrKQogICAgewoJcyA9IGNvbmZpZy0+Zm9udHNbc2V0XTsKCWlmICghcykKCSAgICBjb250aW51ZTsKCWZvciAoZiA9IDA7IGYgPCBzLT5uZm9udDsgZisrKQoJewoJICAgIGlmIChGY0RlYnVnICgpICYgRkNfREJHX01BVENIVikKCSAgICB7CgkJcHJpbnRmICgiRm9udCAlZCAiLCBmKTsKCQlGY1BhdHRlcm5QcmludCAocy0+Zm9udHNbZl0pOwoJICAgIH0KCSAgICBpZiAoIUZjQ29tcGFyZSAocCwgcy0+Zm9udHNbZl0sIHNjb3JlLCByZXN1bHQpKQoJCXJldHVybiAwOwoJICAgIGlmIChGY0RlYnVnICgpICYgRkNfREJHX01BVENIVikKCSAgICB7CgkJcHJpbnRmICgiU2NvcmUiKTsKCQlmb3IgKGkgPSAwOyBpIDwgTlVNX01BVENIRVI7IGkrKykKCQl7CgkJICAgIHByaW50ZiAoIiAlZyIsIHNjb3JlW2ldKTsKCQl9CgkJcHJpbnRmICgiXG4iKTsKCSAgICB9CgkgICAgZm9yIChpID0gMDsgaSA8IE5VTV9NQVRDSEVSOyBpKyspCgkgICAgewoJCWlmIChiZXN0ICYmIGJlc3RzY29yZVtpXSA8IHNjb3JlW2ldKQoJCSAgICBicmVhazsKCQlpZiAoIWJlc3QgfHwgc2NvcmVbaV0gPCBiZXN0c2NvcmVbaV0pCgkJewoJCSAgICBmb3IgKGkgPSAwOyBpIDwgTlVNX01BVENIRVI7IGkrKykKCQkJYmVzdHNjb3JlW2ldID0gc2NvcmVbaV07CgkJICAgIGJlc3QgPSBzLT5mb250c1tmXTsKCQkgICAgYnJlYWs7CgkJfQoJICAgIH0KCX0KICAgIH0KICAgIGlmIChGY0RlYnVnICgpICYgRkNfREJHX01BVENIKQogICAgewoJcHJpbnRmICgiQmVzdCBzY29yZSIpOwoJZm9yIChpID0gMDsgaSA8IE5VTV9NQVRDSEVSOyBpKyspCgkgICAgcHJpbnRmICgiICVnIiwgYmVzdHNjb3JlW2ldKTsKCUZjUGF0dGVyblByaW50IChiZXN0KTsKICAgIH0KICAgIGlmICghYmVzdCkKICAgIHsKCSpyZXN1bHQgPSBGY1Jlc3VsdE5vTWF0Y2g7CglyZXR1cm4gMDsKICAgIH0KICAgIG5ldyA9IEZjUGF0dGVybkNyZWF0ZSAoKTsKICAgIGlmICghbmV3KQoJcmV0dXJuIDA7CiAgICBmb3IgKGkgPSAwOyBpIDwgYmVzdC0+bnVtOyBpKyspCiAgICB7CglmZSA9ICZiZXN0LT5lbHRzW2ldOwoJcGUgPSBGY1BhdHRlcm5GaW5kIChwLCBmZS0+b2JqZWN0LCBGY0ZhbHNlKTsKCWlmIChwZSkKCXsKCSAgICBpZiAoIUZjQ29tcGFyZVZhbHVlTGlzdCAocGUtPm9iamVjdCwgcGUtPnZhbHVlcywgCgkJCQkgICAgIGZlLT52YWx1ZXMsICZ2LCBzY29yZSwgcmVzdWx0KSkKCSAgICB7CgkJRmNQYXR0ZXJuRGVzdHJveSAobmV3KTsKCQlyZXR1cm4gMDsKCSAgICB9Cgl9CgllbHNlCgkgICAgdiA9IGZlLT52YWx1ZXMtPnZhbHVlOwoJRmNQYXR0ZXJuQWRkIChuZXcsIGZlLT5vYmplY3QsIHYsIEZjVHJ1ZSk7CiAgICB9CiAgICBmb3IgKGkgPSAwOyBpIDwgcC0+bnVtOyBpKyspCiAgICB7CglwZSA9ICZwLT5lbHRzW2ldOwoJZmUgPSBGY1BhdHRlcm5GaW5kIChiZXN0LCBwZS0+b2JqZWN0LCBGY0ZhbHNlKTsKCWlmICghZmUpCgkgICAgRmNQYXR0ZXJuQWRkIChuZXcsIHBlLT5vYmplY3QsIHBlLT52YWx1ZXMtPnZhbHVlLCBGY1RydWUpOwogICAgfQogICAgRmNDb25maWdTdWJzdGl0dXRlIChjb25maWcsIG5ldywgRmNNYXRjaEZvbnQpOwogICAgcmV0dXJuIG5ldzsKfQo=