LyoKICogJFhGcmVlODY6ICQKICoKICogQ29weXJpZ2h0IKkgMjAwMSBLZWl0aCBQYWNrYXJkLCBtZW1iZXIgb2YgVGhlIFhGcmVlODYgUHJvamVjdCwgSW5jLgogKgogKiBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlLCBhbmQgc2VsbCB0aGlzIHNvZnR3YXJlIGFuZCBpdHMKICogZG9jdW1lbnRhdGlvbiBmb3IgYW55IHB1cnBvc2UgaXMgaGVyZWJ5IGdyYW50ZWQgd2l0aG91dCBmZWUsIHByb3ZpZGVkIHRoYXQKICogdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYXBwZWFyIGluIGFsbCBjb3BpZXMgYW5kIHRoYXQgYm90aCB0aGF0CiAqIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2UgYXBwZWFyIGluIHN1cHBvcnRpbmcKICogZG9jdW1lbnRhdGlvbiwgYW5kIHRoYXQgdGhlIG5hbWUgb2YgS2VpdGggUGFja2FyZCBub3QgYmUgdXNlZCBpbgogKiBhZHZlcnRpc2luZyBvciBwdWJsaWNpdHkgcGVydGFpbmluZyB0byBkaXN0cmlidXRpb24gb2YgdGhlIHNvZnR3YXJlIHdpdGhvdXQKICogc3BlY2lmaWMsIHdyaXR0ZW4gcHJpb3IgcGVybWlzc2lvbi4gIEtlaXRoIFBhY2thcmQgbWFrZXMgbm8KICogcmVwcmVzZW50YXRpb25zIGFib3V0IHRoZSBzdWl0YWJpbGl0eSBvZiB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZS4gIEl0CiAqIGlzIHByb3ZpZGVkICJhcyBpcyIgd2l0aG91dCBleHByZXNzIG9yIGltcGxpZWQgd2FycmFudHkuCiAqCiAqIEtFSVRIIFBBQ0tBUkQgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEggUkVHQVJEIFRPIFRISVMgU09GVFdBUkUsCiAqIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUywgSU4gTk8KICogRVZFTlQgU0hBTEwgS0VJVEggUEFDS0FSRCBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBJTkRJUkVDVCBPUgogKiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTSBMT1NTIE9GIFVTRSwKICogREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUiBPVEhFUgogKiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SCiAqIFBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuCiAqLwoKI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSAiZmNpbnQuaCIKI2luY2x1ZGUgPGZyZWV0eXBlL2ZyZWV0eXBlLmg+CiNpbmNsdWRlIDxmcmVldHlwZS9pbnRlcm5hbC9mdG9ianMuaD4KI2luY2x1ZGUgPGZyZWV0eXBlL3R0dGFibGVzLmg+CiNpbmNsdWRlIDxmb250Y29uZmlnL2ZjZnJlZXR5cGUuaD4KCnN0YXRpYyBjb25zdCBzdHJ1Y3QgewogICAgaW50CSAgICBiaXQ7CiAgICBjaGFyICAgICpuYW1lOwp9IEZjQ29kZVBhZ2VSYW5nZVtdID0gewogICAgeyAwLAlGQ19MQU5HX0xBVElOXzEgfSwKICAgIHsgMSwJRkNfTEFOR19MQVRJTl8yX0VBU1RFUk5fRVVST1BFIH0sCiAgICB7IDIsCUZDX0xBTkdfQ1lSSUxMSUMgfSwKICAgIHsgMywJRkNfTEFOR19HUkVFSyB9LAogICAgeyA0LAlGQ19MQU5HX1RVUktJU0ggfSwKICAgIHsgNSwJRkNfTEFOR19IRUJSRVcgfSwKICAgIHsgNiwJRkNfTEFOR19BUkFCSUMgfSwKICAgIHsgNywJRkNfTEFOR19XSU5ET1dTX0JBTFRJQyB9LAogICAgeyA4LAlGQ19MQU5HX1ZJRVROQU1FU0UgfSwKLyogOS0xNSByZXNlcnZlZCBmb3IgQWx0ZXJuYXRlIEFOU0kgKi8KICAgIHsgMTYsCUZDX0xBTkdfVEhBSSB9LAogICAgeyAxNywJRkNfTEFOR19KQVBBTkVTRSB9LAogICAgeyAxOCwJRkNfTEFOR19TSU1QTElGSUVEX0NISU5FU0UgfSwKICAgIHsgMTksCUZDX0xBTkdfS09SRUFOX1dBTlNVTkcgfSwKICAgIHsgMjAsCUZDX0xBTkdfVFJBRElUSU9OQUxfQ0hJTkVTRSB9LAogICAgeyAyMSwJRkNfTEFOR19LT1JFQU5fSk9IQUIgfSwKLyogMjItMjggcmVzZXJ2ZWQgZm9yIEFsdGVybmF0ZSBBTlNJICYgT0VNICovCiAgICB7IDI5LAlGQ19MQU5HX01BQ0lOVE9TSCB9LAogICAgeyAzMCwJRkNfTEFOR19PRU0gfSwKICAgIHsgMzEsCUZDX0xBTkdfU1lNQk9MIH0sCi8qIDMyLTQ3IHJlc2VydmVkIGZvciBPRU0gKi8KICAgIHsgNDgsCUZDX0xBTkdfSUJNX0dSRUVLIH0sCiAgICB7IDQ5LAlGQ19MQU5HX01TRE9TX1JVU1NJQU4gfSwKICAgIHsgNTAsCUZDX0xBTkdfTVNET1NfTk9SRElDIH0sCiAgICB7IDUxLAlGQ19MQU5HX0FSQUJJQ184NjQgfSwKICAgIHsgNTIsCUZDX0xBTkdfTVNET1NfQ0FOQURJQU5fRlJFTkNIIH0sCiAgICB7IDUzLAlGQ19MQU5HX0hFQlJFV184NjIgfSwKICAgIHsgNTQsCUZDX0xBTkdfTVNET1NfSUNFTEFORElDIH0sCiAgICB7IDU1LAlGQ19MQU5HX01TRE9TX1BPUlRVR1VFU0UgfSwKICAgIHsgNTYsCUZDX0xBTkdfSUJNX1RVUktJU0ggfSwKICAgIHsgNTcsCUZDX0xBTkdfSUJNX0NZUklMTElDIH0sCiAgICB7IDU4LAlGQ19MQU5HX0xBVElOXzIgfSwKICAgIHsgNTksCUZDX0xBTkdfTVNET1NfQkFMVElDIH0sCiAgICB7IDYwLAlGQ19MQU5HX0dSRUVLXzQzN19HIH0sCiAgICB7IDYxLAlGQ19MQU5HX0FSQUJJQ19BU01PXzcwOCB9LAogICAgeyA2MiwJRkNfTEFOR19XRV9MQVRJTl8xIH0sCiAgICB7IDYzLAlGQ19MQU5HX1VTIH0sCn07CgojZGVmaW5lIE5VTV9DT0RFX1BBR0VfUkFOR0UgKHNpemVvZiBGY0NvZGVQYWdlUmFuZ2UgLyBzaXplb2YgRmNDb2RlUGFnZVJhbmdlWzBdKQoKRmNQYXR0ZXJuICoKRmNGcmVlVHlwZVF1ZXJ5IChjb25zdCBjaGFyICpmaWxlLAoJCSBpbnQJICAgIGlkLAoJCSBGY0JsYW5rcyAgICpibGFua3MsCgkJIGludAkgICAgKmNvdW50KQp7CiAgICBGVF9GYWNlCWZhY2U7CiAgICBGY1BhdHRlcm4JKnBhdDsKICAgIGludAkJc2xhbnQ7CiAgICBpbnQJCXdlaWdodDsKICAgIGludAkJaTsKICAgIEZjQ2hhclNldAkqY3M7CiAgICBGVF9MaWJyYXJ5CWZ0TGlicmFyeTsKICAgIGNvbnN0IGNoYXIJKmZhbWlseTsKICAgIFRUX09TMgkqb3MyOwoKICAgIGlmIChGVF9Jbml0X0ZyZWVUeXBlICgmZnRMaWJyYXJ5KSkKCXJldHVybiAwOwogICAgCiAgICBpZiAoRlRfTmV3X0ZhY2UgKGZ0TGlicmFyeSwgZmlsZSwgaWQsICZmYWNlKSkKCWdvdG8gYmFpbDsKCiAgICAqY291bnQgPSBmYWNlLT5udW1fZmFjZXM7CgogICAgcGF0ID0gRmNQYXR0ZXJuQ3JlYXRlICgpOwogICAgaWYgKCFwYXQpCglnb3RvIGJhaWwwOwoKICAgIGlmICghRmNQYXR0ZXJuQWRkQm9vbCAocGF0LCBGQ19PVVRMSU5FLAoJCQkgICAoZmFjZS0+ZmFjZV9mbGFncyAmIEZUX0ZBQ0VfRkxBR19TQ0FMQUJMRSkgIT0gMCkpCglnb3RvIGJhaWwxOwoKICAgIGlmICghRmNQYXR0ZXJuQWRkQm9vbCAocGF0LCBGQ19TQ0FMQUJMRSwKCQkJICAgKGZhY2UtPmZhY2VfZmxhZ3MgJiBGVF9GQUNFX0ZMQUdfU0NBTEFCTEUpICE9IDApKQoJZ290byBiYWlsMTsKCgogICAgc2xhbnQgPSBGQ19TTEFOVF9ST01BTjsKICAgIGlmIChmYWNlLT5zdHlsZV9mbGFncyAmIEZUX1NUWUxFX0ZMQUdfSVRBTElDKQoJc2xhbnQgPSBGQ19TTEFOVF9JVEFMSUM7CgogICAgaWYgKCFGY1BhdHRlcm5BZGRJbnRlZ2VyIChwYXQsIEZDX1NMQU5ULCBzbGFudCkpCglnb3RvIGJhaWwxOwoKICAgIHdlaWdodCA9IEZDX1dFSUdIVF9NRURJVU07CiAgICBpZiAoZmFjZS0+c3R5bGVfZmxhZ3MgJiBGVF9TVFlMRV9GTEFHX0JPTEQpCgl3ZWlnaHQgPSBGQ19XRUlHSFRfQk9MRDsKCiAgICBpZiAoIUZjUGF0dGVybkFkZEludGVnZXIgKHBhdCwgRkNfV0VJR0hULCB3ZWlnaHQpKQoJZ290byBiYWlsMTsKCiAgICBmYW1pbHkgPSBmYWNlLT5mYW1pbHlfbmFtZTsKICAgIGlmICghZmFtaWx5KQogICAgewoJZmFtaWx5ID0gc3RycmNociAoZmlsZSwgJy8nKTsKCWlmIChmYW1pbHkpCgkgICAgZmFtaWx5Kys7CgllbHNlCgkgICAgZmFtaWx5ID0gZmlsZTsKICAgIH0KICAgIGlmICghRmNQYXR0ZXJuQWRkU3RyaW5nIChwYXQsIEZDX0ZBTUlMWSwgZmFtaWx5KSkKCWdvdG8gYmFpbDE7CgogICAgaWYgKGZhY2UtPnN0eWxlX25hbWUpCiAgICB7CglpZiAoIUZjUGF0dGVybkFkZFN0cmluZyAocGF0LCBGQ19TVFlMRSwgZmFjZS0+c3R5bGVfbmFtZSkpCgkgICAgZ290byBiYWlsMTsKICAgIH0KCiAgICBpZiAoIUZjUGF0dGVybkFkZFN0cmluZyAocGF0LCBGQ19GSUxFLCBmaWxlKSkKCWdvdG8gYmFpbDE7CgogICAgaWYgKCFGY1BhdHRlcm5BZGRJbnRlZ2VyIChwYXQsIEZDX0lOREVYLCBpZCkpCglnb3RvIGJhaWwxOwoKICAgIGlmICghRmNQYXR0ZXJuQWRkU3RyaW5nIChwYXQsIEZDX1NPVVJDRSwgIkZyZWVUeXBlIikpCglnb3RvIGJhaWwxOwoKI2lmIDAKICAgIGlmICgoZmFjZS0+ZmFjZV9mbGFncyAmIEZUX0ZBQ0VfRkxBR19GSVhFRF9XSURUSCkgIT0gMCkKCWlmICghRmNQYXR0ZXJuQWRkSW50ZWdlciAocGF0LCBGQ19TUEFDSU5HLCBGQ19NT05PKSkKCSAgICBnb3RvIGJhaWwxOwojZW5kaWYKCiAgICBjcyA9IEZjRnJlZVR5cGVDaGFyU2V0IChmYWNlLCBibGFua3MpOwogICAgaWYgKCFjcykKCWdvdG8gYmFpbDE7CgogICAgLyoKICAgICAqIFNraXAgb3ZlciBQQ0YgZm9udHMgdGhhdCBoYXZlIG5vIGVuY29kZWQgY2hhcmFjdGVyczsgdGhleSdyZQogICAgICogdXN1YWxseSBqdXN0IFVuaWNvZGUgZm9udHMgdHJhbnNjb2RlZCB0byBzb21lIGxlZ2FjeSBlbmNvZGluZwogICAgICovCiAgICBpZiAoRmNDaGFyU2V0Q291bnQgKGNzKSA9PSAwKQogICAgewoJaWYgKCFzdHJjbXAoRlRfTU9EVUxFX0NMQVNTKCZmYWNlLT5kcml2ZXItPnJvb3QpLT5tb2R1bGVfbmFtZSwgInBjZiIpKQoJICAgIGdvdG8gYmFpbDI7CiAgICB9CgogICAgaWYgKCFGY1BhdHRlcm5BZGRDaGFyU2V0IChwYXQsIEZDX0NIQVJTRVQsIGNzKSkKCWdvdG8gYmFpbDI7CiAgICAvKgogICAgICogRHJvcCBvdXIgcmVmZXJlbmNlIHRvIHRoZSBjaGFyc2V0CiAgICAgKi8KICAgIEZjQ2hhclNldERlc3Ryb3kgKGNzKTsKICAgIAogICAgaWYgKCEoZmFjZS0+ZmFjZV9mbGFncyAmIEZUX0ZBQ0VfRkxBR19TQ0FMQUJMRSkpCiAgICB7Cglmb3IgKGkgPSAwOyBpIDwgZmFjZS0+bnVtX2ZpeGVkX3NpemVzOyBpKyspCgkgICAgaWYgKCFGY1BhdHRlcm5BZGREb3VibGUgKHBhdCwgRkNfUElYRUxfU0laRSwKCQkJCSAgICAgKGRvdWJsZSkgZmFjZS0+YXZhaWxhYmxlX3NpemVzW2ldLmhlaWdodCkpCgkJZ290byBiYWlsMTsKCWlmICghRmNQYXR0ZXJuQWRkQm9vbCAocGF0LCBGQ19BTlRJQUxJQVMsIEZjRmFsc2UpKQoJICAgIGdvdG8gYmFpbDE7CiAgICB9CgogICAgLyoKICAgICAqIEdldCB0aGUgT1MvMiB0YWJsZSBhbmQgcG9rZSBhYm91dAogICAgICovCiAgICBvczIgPSAoVFRfT1MyICopIEZUX0dldF9TZm50X1RhYmxlIChmYWNlLCBmdF9zZm50X29zMik7CiAgICBpZiAob3MyICYmIG9zMi0+dmVyc2lvbiA+PSAweDAwMDEgJiYgb3MyLT52ZXJzaW9uICE9IDB4ZmZmZikKICAgIHsKCWZvciAoaSA9IDA7IGkgPCBOVU1fQ09ERV9QQUdFX1JBTkdFOyBpKyspCgl7CgkgICAgRlRfVUxvbmcJYml0czsKCSAgICBpbnQJCWJpdDsKCSAgICBpZiAoRmNDb2RlUGFnZVJhbmdlW2ldLmJpdCA8IDMyKQoJICAgIHsKCQliaXRzID0gb3MyLT51bENvZGVQYWdlUmFuZ2UxOwoJCWJpdCA9IEZjQ29kZVBhZ2VSYW5nZVtpXS5iaXQ7CgkgICAgfQoJICAgIGVsc2UKCSAgICB7CgkJYml0cyA9IG9zMi0+dWxDb2RlUGFnZVJhbmdlMjsKCQliaXQgPSBGY0NvZGVQYWdlUmFuZ2VbaV0uYml0IC0gMzI7CgkgICAgfQoJICAgIGlmIChiaXRzICYgKDEgPDwgYml0KSkKCSAgICB7CgkJaWYgKCFGY1BhdHRlcm5BZGRTdHJpbmcgKHBhdCwgRkNfTEFORywKCQkJCQkgRmNDb2RlUGFnZVJhbmdlW2ldLm5hbWUpKQoJCSAgICBnb3RvIGJhaWwxOwoJICAgIH0KCX0KICAgIH0KCiAgICBGVF9Eb25lX0ZhY2UgKGZhY2UpOwogICAgRlRfRG9uZV9GcmVlVHlwZSAoZnRMaWJyYXJ5KTsKICAgIHJldHVybiBwYXQ7CgpiYWlsMjoKICAgIEZjQ2hhclNldERlc3Ryb3kgKGNzKTsKYmFpbDE6CiAgICBGY1BhdHRlcm5EZXN0cm95IChwYXQpOwpiYWlsMDoKICAgIEZUX0RvbmVfRmFjZSAoZmFjZSk7CmJhaWw6CiAgICBGVF9Eb25lX0ZyZWVUeXBlIChmdExpYnJhcnkpOwogICAgcmV0dXJuIDA7Cn0K