Ly8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyBCaXRtYXAgY29udmVyc2lvbiByb3V0aW5lcwovLwovLyBEZXNpZ24gYW5kIGltcGxlbWVudGF0aW9uIGJ5Ci8vIC0gSGVydukgRHJvbG9uIChkcm9sb25AaW5mb25pZS5mcikKLy8KLy8gVGhpcyBmaWxlIGlzIHBhcnQgb2YgRnJlZUltYWdlIDMKLy8KLy8gQ09WRVJFRCBDT0RFIElTIFBST1ZJREVEIFVOREVSIFRISVMgTElDRU5TRSBPTiBBTiAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRZCi8vIE9GIEFOWSBLSU5ELCBFSVRIRVIgRVhQUkVTU0VEIE9SIElNUExJRUQsIElOQ0xVRElORywgV0lUSE9VVCBMSU1JVEFUSU9OLCBXQVJSQU5USUVTCi8vIFRIQVQgVEhFIENPVkVSRUQgQ09ERSBJUyBGUkVFIE9GIERFRkVDVFMsIE1FUkNIQU5UQUJMRSwgRklUIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRQovLyBPUiBOT04tSU5GUklOR0lORy4gVEhFIEVOVElSRSBSSVNLIEFTIFRPIFRIRSBRVUFMSVRZIEFORCBQRVJGT1JNQU5DRSBPRiBUSEUgQ09WRVJFRAovLyBDT0RFIElTIFdJVEggWU9VLiBTSE9VTEQgQU5ZIENPVkVSRUQgQ09ERSBQUk9WRSBERUZFQ1RJVkUgSU4gQU5ZIFJFU1BFQ1QsIFlPVSAoTk9UCi8vIFRIRSBJTklUSUFMIERFVkVMT1BFUiBPUiBBTlkgT1RIRVIgQ09OVFJJQlVUT1IpIEFTU1VNRSBUSEUgQ09TVCBPRiBBTlkgTkVDRVNTQVJZCi8vIFNFUlZJQ0lORywgUkVQQUlSIE9SIENPUlJFQ1RJT04uIFRISVMgRElTQ0xBSU1FUiBPRiBXQVJSQU5UWSBDT05TVElUVVRFUyBBTiBFU1NFTlRJQUwKLy8gUEFSVCBPRiBUSElTIExJQ0VOU0UuIE5PIFVTRSBPRiBBTlkgQ09WRVJFRCBDT0RFIElTIEFVVEhPUklaRUQgSEVSRVVOREVSIEVYQ0VQVCBVTkRFUgovLyBUSElTIERJU0NMQUlNRVIuCi8vCi8vIFVzZSBhdCB5b3VyIG93biByaXNrIQovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojaW5jbHVkZSAiRnJlZUltYWdlLmgiCiNpbmNsdWRlICJVdGlsaXRpZXMuaCIKCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gICBzbWFydCBjb252ZXJ0IFggdG8gUkdCRgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpGSUJJVE1BUCAqIERMTF9DQUxMQ09OVgpGcmVlSW1hZ2VfQ29udmVydFRvUkdCRihGSUJJVE1BUCAqZGliKSB7CglGSUJJVE1BUCAqc3JjID0gTlVMTDsKCUZJQklUTUFQICpkc3QgPSBOVUxMOwoKCWNvbnN0IEZSRUVfSU1BR0VfVFlQRSBzcmNfdHlwZSA9IEZyZWVJbWFnZV9HZXRJbWFnZVR5cGUoZGliKTsKCgkvLyBjaGVjayBmb3IgYWxsb3dlZCBjb252ZXJzaW9ucyAKCXN3aXRjaChzcmNfdHlwZSkgewoJCWNhc2UgRklUX0JJVE1BUDoKCQl7CgkJCS8vIGFsbG93IGNvbnZlcnNpb24gZnJvbSAyNC0gYW5kIDMyLWJpdAoJCQljb25zdCBGUkVFX0lNQUdFX0NPTE9SX1RZUEUgY29sb3JfdHlwZSA9IEZyZWVJbWFnZV9HZXRDb2xvclR5cGUoZGliKTsKCQkJaWYoKGNvbG9yX3R5cGUgIT0gRklDX1JHQikgJiYgKGNvbG9yX3R5cGUgIT0gRklDX1JHQkFMUEhBKSkgewoJCQkJc3JjID0gRnJlZUltYWdlX0NvbnZlcnRUbzI0Qml0cyhkaWIpOwoJCQkJaWYoIXNyYykgcmV0dXJuIE5VTEw7CgkJCX0gZWxzZSB7CgkJCQlzcmMgPSBkaWI7CgkJCX0KCQkJYnJlYWs7CgkJfQoJCWNhc2UgRklUX1JHQjE2OgoJCQkvLyBhbGxvdyBjb252ZXJzaW9uIGZyb20gNDgtYml0CgkJCXNyYyA9IGRpYjsKCQkJYnJlYWs7CgkJY2FzZSBGSVRfUkdCQUY6CgkJCS8vIGFsbG93IGNvbnZlcnNpb24gZnJvbSAxMjgtYml0CgkJCXNyYyA9IGRpYjsKCQkJYnJlYWs7CgkJY2FzZSBGSVRfUkdCRjoKCQkJLy8gUkdCRiB0eXBlIDogY2xvbmUgdGhlIHNyYwoJCQlyZXR1cm4gRnJlZUltYWdlX0Nsb25lKGRpYik7CgkJCWJyZWFrOwoJCWRlZmF1bHQ6CgkJCXJldHVybiBOVUxMOwoJfQoKCS8vIGFsbG9jYXRlIGRzdCBpbWFnZQoKCWNvbnN0IHVuc2lnbmVkIHdpZHRoID0gRnJlZUltYWdlX0dldFdpZHRoKHNyYyk7Cgljb25zdCB1bnNpZ25lZCBoZWlnaHQgPSBGcmVlSW1hZ2VfR2V0SGVpZ2h0KHNyYyk7CgoJZHN0ID0gRnJlZUltYWdlX0FsbG9jYXRlVChGSVRfUkdCRiwgd2lkdGgsIGhlaWdodCk7CglpZighZHN0KSByZXR1cm4gTlVMTDsKCgkvLyBjb3B5IG1ldGFkYXRhIGZyb20gc3JjIHRvIGRzdAoJRnJlZUltYWdlX0Nsb25lTWV0YWRhdGEoZHN0LCBzcmMpOwoKCS8vIGNvbnZlcnQgZnJvbSBzcmMgdHlwZSB0byBSR0JGCgoJY29uc3QgdW5zaWduZWQgc3JjX3BpdGNoID0gRnJlZUltYWdlX0dldFBpdGNoKHNyYyk7Cgljb25zdCB1bnNpZ25lZCBkc3RfcGl0Y2ggPSBGcmVlSW1hZ2VfR2V0UGl0Y2goZHN0KTsKCglzd2l0Y2goc3JjX3R5cGUpIHsKCQljYXNlIEZJVF9CSVRNQVA6CgkJewoJCQkvLyBjYWxjdWxhdGUgdGhlIG51bWJlciBvZiBieXRlcyBwZXIgcGl4ZWwgKDMgZm9yIDI0LWJpdCBvciA0IGZvciAzMi1iaXQpCgkJCWNvbnN0IHVuc2lnbmVkIGJ5dGVzcHAgPSBGcmVlSW1hZ2VfR2V0TGluZShzcmMpIC8gRnJlZUltYWdlX0dldFdpZHRoKHNyYyk7CgoJCQljb25zdCBCWVRFICpzcmNfYml0cyA9IChCWVRFKilGcmVlSW1hZ2VfR2V0Qml0cyhzcmMpOwoJCQlCWVRFICpkc3RfYml0cyA9IChCWVRFKilGcmVlSW1hZ2VfR2V0Qml0cyhkc3QpOwoKCQkJZm9yKHVuc2lnbmVkIHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKCQkJCWNvbnN0IEJZVEUgICAqc3JjX3BpeGVsID0gKEJZVEUqKXNyY19iaXRzOwoJCQkJRklSR0JGICpkc3RfcGl4ZWwgPSAoRklSR0JGKilkc3RfYml0czsKCQkJCWZvcih1bnNpZ25lZCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKCQkJCQkvLyBjb252ZXJ0IGFuZCBzY2FsZSB0byB0aGUgcmFuZ2UgWzAuLjFdCgkJCQkJZHN0X3BpeGVsLT5yZWQgICA9IChmbG9hdCkoc3JjX3BpeGVsW0ZJX1JHQkFfUkVEXSkgICAvIDI1NTsKCQkJCQlkc3RfcGl4ZWwtPmdyZWVuID0gKGZsb2F0KShzcmNfcGl4ZWxbRklfUkdCQV9HUkVFTl0pIC8gMjU1OwoJCQkJCWRzdF9waXhlbC0+Ymx1ZSAgPSAoZmxvYXQpKHNyY19waXhlbFtGSV9SR0JBX0JMVUVdKSAgLyAyNTU7CgoJCQkJCXNyY19waXhlbCArPSBieXRlc3BwOwoJCQkJCWRzdF9waXhlbCArKzsKCQkJCX0KCQkJCXNyY19iaXRzICs9IHNyY19waXRjaDsKCQkJCWRzdF9iaXRzICs9IGRzdF9waXRjaDsKCQkJfQoJCX0KCQlicmVhazsKCgkJY2FzZSBGSVRfUkdCMTY6CgkJewoJCQljb25zdCBCWVRFICpzcmNfYml0cyA9IChCWVRFKilGcmVlSW1hZ2VfR2V0Qml0cyhzcmMpOwoJCQlCWVRFICpkc3RfYml0cyA9IChCWVRFKilGcmVlSW1hZ2VfR2V0Qml0cyhkc3QpOwoKCQkJZm9yKHVuc2lnbmVkIHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKCQkJCWNvbnN0IEZJUkdCMTYgKnNyY19waXhlbCA9IChGSVJHQjE2Kikgc3JjX2JpdHM7CgkJCQlGSVJHQkYgICpkc3RfcGl4ZWwgPSAoRklSR0JGKikgIGRzdF9iaXRzOwoKCQkJCWZvcih1bnNpZ25lZCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKCQkJCQkvLyBjb252ZXJ0IGFuZCBzY2FsZSB0byB0aGUgcmFuZ2UgWzAuLjFdCgkJCQkJZHN0X3BpeGVsW3hdLnJlZCAgID0gKGZsb2F0KShzcmNfcGl4ZWxbeF0ucmVkKSAgIC8gNjU1MzU7CgkJCQkJZHN0X3BpeGVsW3hdLmdyZWVuID0gKGZsb2F0KShzcmNfcGl4ZWxbeF0uZ3JlZW4pIC8gNjU1MzU7CgkJCQkJZHN0X3BpeGVsW3hdLmJsdWUgID0gKGZsb2F0KShzcmNfcGl4ZWxbeF0uYmx1ZSkgIC8gNjU1MzU7CgkJCQl9CgkJCQlzcmNfYml0cyArPSBzcmNfcGl0Y2g7CgkJCQlkc3RfYml0cyArPSBkc3RfcGl0Y2g7CgkJCX0KCQl9CgkJYnJlYWs7CgoJCWNhc2UgRklUX1JHQkExNjoKCQl7CgkJCWNvbnN0IEJZVEUgKnNyY19iaXRzID0gKEJZVEUqKUZyZWVJbWFnZV9HZXRCaXRzKHNyYyk7CgkJCUJZVEUgKmRzdF9iaXRzID0gKEJZVEUqKUZyZWVJbWFnZV9HZXRCaXRzKGRzdCk7CgoJCQlmb3IodW5zaWduZWQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewoJCQkJY29uc3QgRklSR0JBMTYgKnNyY19waXhlbCA9IChGSVJHQkExNiopIHNyY19iaXRzOwoJCQkJRklSR0JGICAqZHN0X3BpeGVsID0gKEZJUkdCRiopICBkc3RfYml0czsKCgkJCQlmb3IodW5zaWduZWQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7CgkJCQkJLy8gY29udmVydCBhbmQgc2NhbGUgdG8gdGhlIHJhbmdlIFswLi4xXQoJCQkJCWRzdF9waXhlbFt4XS5yZWQgICA9IChmbG9hdCkoc3JjX3BpeGVsW3hdLnJlZCkgICAvIDY1NTM1OwoJCQkJCWRzdF9waXhlbFt4XS5ncmVlbiA9IChmbG9hdCkoc3JjX3BpeGVsW3hdLmdyZWVuKSAvIDY1NTM1OwoJCQkJCWRzdF9waXhlbFt4XS5ibHVlICA9IChmbG9hdCkoc3JjX3BpeGVsW3hdLmJsdWUpICAvIDY1NTM1OwoJCQkJfQoJCQkJc3JjX2JpdHMgKz0gc3JjX3BpdGNoOwoJCQkJZHN0X2JpdHMgKz0gZHN0X3BpdGNoOwoJCQl9CgkJfQoJCWJyZWFrOwoKCQljYXNlIEZJVF9SR0JBRjoKCQl7CgkJCWNvbnN0IEJZVEUgKnNyY19iaXRzID0gKEJZVEUqKUZyZWVJbWFnZV9HZXRCaXRzKHNyYyk7CgkJCUJZVEUgKmRzdF9iaXRzID0gKEJZVEUqKUZyZWVJbWFnZV9HZXRCaXRzKGRzdCk7CgoJCQlmb3IodW5zaWduZWQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewoJCQkJY29uc3QgRklSR0JBRiAqc3JjX3BpeGVsID0gKEZJUkdCQUYqKSBzcmNfYml0czsKCQkJCUZJUkdCRiAgKmRzdF9waXhlbCA9IChGSVJHQkYqKSAgZHN0X2JpdHM7CgoJCQkJZm9yKHVuc2lnbmVkIHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewoJCQkJCS8vIGNvbnZlcnQgYW5kIHNraXAgYWxwaGEgY2hhbm5lbAoJCQkJCWRzdF9waXhlbFt4XS5yZWQgICA9IHNyY19waXhlbFt4XS5yZWQ7CgkJCQkJZHN0X3BpeGVsW3hdLmdyZWVuID0gc3JjX3BpeGVsW3hdLmdyZWVuOwoJCQkJCWRzdF9waXhlbFt4XS5ibHVlICA9IHNyY19waXhlbFt4XS5ibHVlOwoJCQkJfQoJCQkJc3JjX2JpdHMgKz0gc3JjX3BpdGNoOwoJCQkJZHN0X2JpdHMgKz0gZHN0X3BpdGNoOwoJCQl9CgkJfQoJCWJyZWFrOwoJfQoKCWlmKHNyYyAhPSBkaWIpIHsKCQlGcmVlSW1hZ2VfVW5sb2FkKHNyYyk7Cgl9CgoJcmV0dXJuIGRzdDsKfQoK