Ly8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyBmaXBXaW5JbWFnZSBjbGFzcyBpbXBsZW1lbnRhdGlvbgovLwovLyBEZXNpZ24gYW5kIGltcGxlbWVudGF0aW9uIGJ5Ci8vIC0gSGVydukgRHJvbG9uIChkcm9sb25AaW5mb25pZS5mcikKLy8KLy8gVGhpcyBmaWxlIGlzIHBhcnQgb2YgRnJlZUltYWdlIDMKLy8KLy8gQ09WRVJFRCBDT0RFIElTIFBST1ZJREVEIFVOREVSIFRISVMgTElDRU5TRSBPTiBBTiAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRZCi8vIE9GIEFOWSBLSU5ELCBFSVRIRVIgRVhQUkVTU0VEIE9SIElNUExJRUQsIElOQ0xVRElORywgV0lUSE9VVCBMSU1JVEFUSU9OLCBXQVJSQU5USUVTCi8vIFRIQVQgVEhFIENPVkVSRUQgQ09ERSBJUyBGUkVFIE9GIERFRkVDVFMsIE1FUkNIQU5UQUJMRSwgRklUIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRQovLyBPUiBOT04tSU5GUklOR0lORy4gVEhFIEVOVElSRSBSSVNLIEFTIFRPIFRIRSBRVUFMSVRZIEFORCBQRVJGT1JNQU5DRSBPRiBUSEUgQ09WRVJFRAovLyBDT0RFIElTIFdJVEggWU9VLiBTSE9VTEQgQU5ZIENPVkVSRUQgQ09ERSBQUk9WRSBERUZFQ1RJVkUgSU4gQU5ZIFJFU1BFQ1QsIFlPVSAoTk9UCi8vIFRIRSBJTklUSUFMIERFVkVMT1BFUiBPUiBBTlkgT1RIRVIgQ09OVFJJQlVUT1IpIEFTU1VNRSBUSEUgQ09TVCBPRiBBTlkgTkVDRVNTQVJZCi8vIFNFUlZJQ0lORywgUkVQQUlSIE9SIENPUlJFQ1RJT04uIFRISVMgRElTQ0xBSU1FUiBPRiBXQVJSQU5UWSBDT05TVElUVVRFUyBBTiBFU1NFTlRJQUwKLy8gUEFSVCBPRiBUSElTIExJQ0VOU0UuIE5PIFVTRSBPRiBBTlkgQ09WRVJFRCBDT0RFIElTIEFVVEhPUklaRUQgSEVSRVVOREVSIEVYQ0VQVCBVTkRFUgovLyBUSElTIERJU0NMQUlNRVIuCi8vCi8vIFVzZSBhdCB5b3VyIG93biByaXNrIQovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojaW5jbHVkZSAiRnJlZUltYWdlUGx1cy5oIgoKI2lmZGVmIF9XSU4zMgoKLy8gbWFya2VyIHVzZWQgZm9yIGNsaXBib2FyZCBjb3B5IC8gcGFzdGUKCnN0YXRpYyBpbmxpbmUgdm9pZCAKU0VUX0ZSRUVJTUFHRV9NQVJLRVIoQklUTUFQSU5GT0hFQURFUiAqYm1paCwgRklCSVRNQVAgKmRpYikgewoJLy8gV2luZG93cyBjb25zdGFudHMgZ29lcyBmcm9tIDBMIHRvIDVMCgkvLyBBZGQgMHhGRiB0byBhdm9pZCBjb25mbGljdHMKCWJtaWgtPmJpQ29tcHJlc3Npb24gPSAweEZGICsgRnJlZUltYWdlX0dldEltYWdlVHlwZShkaWIpOwp9CgpzdGF0aWMgaW5saW5lIEZSRUVfSU1BR0VfVFlQRSAKR0VUX0ZSRUVJTUFHRV9NQVJLRVIoQklUTUFQSU5GT0hFQURFUiAqYm1paCkgewoJcmV0dXJuIChGUkVFX0lNQUdFX1RZUEUpKGJtaWgtPmJpQ29tcHJlc3Npb24gLSAweEZGKTsKfQoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwovLyBDb25zdHJ1Y3Rpb24gLyBEZXN0cnVjdGlvbgoKZmlwV2luSW1hZ2U6OmZpcFdpbkltYWdlKEZSRUVfSU1BR0VfVFlQRSBpbWFnZV90eXBlLCB1bnNpZ25lZCB3aWR0aCwgdW5zaWduZWQgaGVpZ2h0LCB1bnNpZ25lZCBicHApIDogZmlwSW1hZ2UoaW1hZ2VfdHlwZSwgd2lkdGgsIGhlaWdodCwgYnBwKSB7CglfZGlzcGxheV9kaWIgPSBOVUxMOwoJX2JEZWxldGVNZSA9IEZBTFNFOwoJLy8gZGVmYXVsdCB0b25lIG1hcHBpbmcgb3BlcmF0b3IKCV90bW8gPSBGSVRNT19EUkFHTzAzOwoJX3Rtb19wYXJhbV8xID0gMDsKCV90bW9fcGFyYW1fMiA9IDA7CglfdG1vX3BhcmFtXzMgPSAxOwoJX3Rtb19wYXJhbV80ID0gMDsKfQoKZmlwV2luSW1hZ2U6On5maXBXaW5JbWFnZSgpIHsgCglpZihfYkRlbGV0ZU1lKSB7CgkJRnJlZUltYWdlX1VubG9hZChfZGlzcGxheV9kaWIpOwoJfQp9Cgp2b2lkIGZpcFdpbkltYWdlOjpjbGVhcigpIHsKCS8vIGRlbGV0ZSBfZGlzcGxheV9kaWIKCWlmKF9iRGVsZXRlTWUpIHsKCQlGcmVlSW1hZ2VfVW5sb2FkKF9kaXNwbGF5X2RpYik7Cgl9CglfZGlzcGxheV9kaWIgPSBOVUxMOwoJX2JEZWxldGVNZSA9IEZBTFNFOwoJLy8gZGVsZXRlIGJhc2UgY2xhc3MgZGF0YQoJZmlwSW1hZ2U6OmNsZWFyKCk7Cn0KCkJPT0wgZmlwV2luSW1hZ2U6OmlzVmFsaWQoKSBjb25zdCB7CglyZXR1cm4gZmlwSW1hZ2U6OmlzVmFsaWQoKTsKfQoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwovLyBDb3B5aW5nCgpmaXBXaW5JbWFnZSYgZmlwV2luSW1hZ2U6Om9wZXJhdG9yPShjb25zdCBmaXBJbWFnZSYgSW1hZ2UpIHsKCS8vIGRlbGV0ZSBfZGlzcGxheV9kaWIKCWlmKF9iRGVsZXRlTWUpIHsKCQlGcmVlSW1hZ2VfVW5sb2FkKF9kaXNwbGF5X2RpYik7Cgl9CglfZGlzcGxheV9kaWIgPSBOVUxMOwoJX2JEZWxldGVNZSA9IEZBTFNFOwoJLy8gY2xvbmUgdGhlIGJhc2UgY2xhc3MKCWZpcEltYWdlOjpvcGVyYXRvcj0oSW1hZ2UpOwoKCXJldHVybiAqdGhpczsKfQoKZmlwV2luSW1hZ2UmIGZpcFdpbkltYWdlOjpvcGVyYXRvcj0oY29uc3QgZmlwV2luSW1hZ2UmIEltYWdlKSB7CglpZih0aGlzICE9ICZJbWFnZSkgewoJCS8vIGRlbGV0ZSBfZGlzcGxheV9kaWIKCQlpZihfYkRlbGV0ZU1lKSB7CgkJCUZyZWVJbWFnZV9VbmxvYWQoX2Rpc3BsYXlfZGliKTsKCQl9CgkJX2Rpc3BsYXlfZGliID0gTlVMTDsKCQlfYkRlbGV0ZU1lID0gRkFMU0U7CgkJLy8gY29weSB0bW8gZGF0YQoJCV90bW8gPSBJbWFnZS5fdG1vOwoJCV90bW9fcGFyYW1fMSA9IEltYWdlLl90bW9fcGFyYW1fMTsKCQlfdG1vX3BhcmFtXzIgPSBJbWFnZS5fdG1vX3BhcmFtXzI7CgkJX3Rtb19wYXJhbV8zID0gSW1hZ2UuX3Rtb19wYXJhbV8zOwoJCV90bW9fcGFyYW1fNCA9IEltYWdlLl90bW9fcGFyYW1fNDsKCgkJLy8gY2xvbmUgdGhlIGJhc2UgY2xhc3MKCQlmaXBJbWFnZTo6b3BlcmF0b3I9KEltYWdlKTsKCX0KCXJldHVybiAqdGhpczsKfQoKSEFORExFIGZpcFdpbkltYWdlOjpjb3B5VG9IYW5kbGUoKSBjb25zdCB7CglIQU5ETEUgaE1lbSA9IE5VTEw7CgoJaWYoX2RpYikgewoKCQkvLyBHZXQgZXF1aXZhbGVudCBESUIgc2l6ZQoJCWxvbmcgZGliX3NpemUgPSBzaXplb2YoQklUTUFQSU5GT0hFQURFUik7CgkJZGliX3NpemUgKz0gRnJlZUltYWdlX0dldENvbG9yc1VzZWQoX2RpYikgKiBzaXplb2YoUkdCUVVBRCk7CgkJZGliX3NpemUgKz0gRnJlZUltYWdlX0dldFBpdGNoKF9kaWIpICogRnJlZUltYWdlX0dldEhlaWdodChfZGliKTsKCgkJLy8gQWxsb2NhdGUgYSBESUIKCQloTWVtID0gR2xvYmFsQWxsb2MoR0hORCwgZGliX3NpemUpOwoJCUJZVEUgKmRpYiA9IChCWVRFKilHbG9iYWxMb2NrKGhNZW0pOwoKCQltZW1zZXQoZGliLCAwLCBkaWJfc2l6ZSk7CgoJCUJZVEUgKnBfZGliID0gKEJZVEUqKWRpYjsKCgkJLy8gQ29weSB0aGUgQklUTUFQSU5GT0hFQURFUgoKCQlCSVRNQVBJTkZPSEVBREVSICpiaWggPSBGcmVlSW1hZ2VfR2V0SW5mb0hlYWRlcihfZGliKTsKCQltZW1jcHkocF9kaWIsIGJpaCwgc2l6ZW9mKEJJVE1BUElORk9IRUFERVIpKTsKCQlpZihGcmVlSW1hZ2VfR2V0SW1hZ2VUeXBlKF9kaWIpICE9IEZJVF9CSVRNQVApIHsKCQkJLy8gdGhpcyBoYWNrIGlzIHVzZWQgdG8gc3RvcmUgdGhlIGJpdG1hcCB0eXBlIGluIHRoZSBiaUNvbXByZXNzaW9uIG1lbWJlciBvZiB0aGUgQklUTUFQSU5GT0hFQURFUgoJCQlTRVRfRlJFRUlNQUdFX01BUktFUigoQklUTUFQSU5GT0hFQURFUiopcF9kaWIsIF9kaWIpOwoJCX0KCQlwX2RpYiArPSBzaXplb2YoQklUTUFQSU5GT0hFQURFUik7CgoJCS8vIENvcHkgdGhlIHBhbGV0dGUKCgkJUkdCUVVBRCAqcGFsID0gRnJlZUltYWdlX0dldFBhbGV0dGUoX2RpYik7CgkJbWVtY3B5KHBfZGliLCBwYWwsIEZyZWVJbWFnZV9HZXRDb2xvcnNVc2VkKF9kaWIpICogc2l6ZW9mKFJHQlFVQUQpKTsKCQlwX2RpYiArPSBGcmVlSW1hZ2VfR2V0Q29sb3JzVXNlZChfZGliKSAqIHNpemVvZihSR0JRVUFEKTsKCgkJLy8gQ29weSB0aGUgYml0bWFwCgoJCUJZVEUgKmJpdHMgPSBGcmVlSW1hZ2VfR2V0Qml0cyhfZGliKTsKCQltZW1jcHkocF9kaWIsIGJpdHMsIEZyZWVJbWFnZV9HZXRQaXRjaChfZGliKSAqIEZyZWVJbWFnZV9HZXRIZWlnaHQoX2RpYikpOwoKCQlHbG9iYWxVbmxvY2soaE1lbSk7Cgl9CgoJcmV0dXJuIGhNZW07Cn0KCkJPT0wgZmlwV2luSW1hZ2U6OmNvcHlGcm9tSGFuZGxlKEhBTkRMRSBoTWVtKSB7CglCWVRFICpscFZvaWQgPSBOVUxMOwoJQklUTUFQSU5GT0hFQURFUiAqcEhlYWQgPSBOVUxMOwoJUkdCUVVBRCAqcFBhbGV0dGUgPSBOVUxMOwoJQllURSAqYml0cyA9IE5VTEw7CglEV09SRCBiaXRmaWVsZHNbM10gPSB7MCwgMCwgMH07CgoJLy8gR2V0IGEgcG9pbnRlciB0byB0aGUgYml0bWFwCglscFZvaWQgPSAoQllURSAqKUdsb2JhbExvY2soaE1lbSk7CgoJLy8gR2V0IGEgcG9pbnRlciB0byB0aGUgYml0bWFwIGhlYWRlcgoJcEhlYWQgPSAoQklUTUFQSU5GT0hFQURFUiAqKWxwVm9pZDsKCgkvLyBHZXQgYSBwb2ludGVyIHRvIHRoZSBwYWxldHRlCglpZihwSGVhZC0+YmlCaXRDb3VudCA8IDE2KQoJCXBQYWxldHRlID0gKFJHQlFVQUQgKikoKChCWVRFICopcEhlYWQpICsgc2l6ZW9mKEJJVE1BUElORk9IRUFERVIpKTsKCgkvLyBHZXQgYSBwb2ludGVyIHRvIHRoZSBwaXhlbHMKCWJpdHMgPSAoKEJZVEUqKXBIZWFkICsgc2l6ZW9mKEJJVE1BUElORk9IRUFERVIpICsgc2l6ZW9mKFJHQlFVQUQpICogcEhlYWQtPmJpQ2xyVXNlZCk7CgoJaWYocEhlYWQtPmJpQ29tcHJlc3Npb24gPT0gQklfQklURklFTERTKSB7CgkJLy8gVGFrZSBpbnRvIGFjY291bnQgdGhlIGNvbG9yIG1hc2tzIHRoYXQgc3BlY2lmeSB0aGUgcmVkLCBncmVlbiwgYW5kIGJsdWUgY29tcG9uZW50cyAoMTYtIGFuZCAzMi1iaXQpCgkJdW5zaWduZWQgbWFza19zaXplID0gMyAqIHNpemVvZihEV09SRCk7CgkJbWVtY3B5KCZiaXRmaWVsZHNbMF0sIGJpdHMsIG1hc2tfc2l6ZSk7CgkJYml0cyArPSBtYXNrX3NpemU7Cgl9IAoKCWlmKGxwVm9pZCkgewoKCQkvLyBBbGxvY2F0ZSBhIG5ldyBGSUJJVE1BUAoKCQlGUkVFX0lNQUdFX1RZUEUgaW1hZ2VfdHlwZSA9IEZJVF9CSVRNQVA7CgkJLy8gVXNlIGEgaGFjayB0byBkZWNpZGUgaWYgdGhlIGNsaXBib2FyZCBjb250YWlucyBub24gc3RhbmRhcmQgYml0bWFwcyAuLi4KCQlzd2l0Y2goR0VUX0ZSRUVJTUFHRV9NQVJLRVIocEhlYWQpKSB7CgkJCWNhc2UgRklUX1VJTlQxNjoKCQkJY2FzZSBGSVRfSU5UMTY6CgkJCWNhc2UgRklUX1VJTlQzMjoKCQkJY2FzZSBGSVRfSU5UMzI6CgkJCWNhc2UgRklUX0ZMT0FUOgoJCQljYXNlIEZJVF9ET1VCTEU6CgkJCWNhc2UgRklUX0NPTVBMRVg6CgkJCWNhc2UgRklUX1JHQjE2OgoJCQljYXNlIEZJVF9SR0JBMTY6CgkJCWNhc2UgRklUX1JHQkY6CgkJCWNhc2UgRklUX1JHQkFGOgoJCQkJaW1hZ2VfdHlwZSA9IEdFVF9GUkVFSU1BR0VfTUFSS0VSKHBIZWFkKTsKCQkJCWJyZWFrOwoJCX0KCQlpZighc2V0U2l6ZShpbWFnZV90eXBlLCAoV09SRClwSGVhZC0+YmlXaWR0aCwgKFdPUkQpcEhlYWQtPmJpSGVpZ2h0LCBwSGVhZC0+YmlCaXRDb3VudCwgYml0ZmllbGRzWzJdLCBiaXRmaWVsZHNbMV0sIGJpdGZpZWxkc1swXSkpIHsKCQkJR2xvYmFsVW5sb2NrKGxwVm9pZCk7CgkJCXJldHVybiBGQUxTRTsKCQl9CgoJCS8vIENvcHkgdGhlIGJpdG1hcCBoZWFkZXIKCQltZW1jcHkoRnJlZUltYWdlX0dldEluZm9IZWFkZXIoX2RpYiksIHBIZWFkLCBzaXplb2YoQklUTUFQSU5GT0hFQURFUikpOwoKCgkJLy8gQ29weSB0aGUgcGFsZXR0ZQoJCW1lbWNweShGcmVlSW1hZ2VfR2V0UGFsZXR0ZShfZGliKSwgcFBhbGV0dGUsIHBIZWFkLT5iaUNsclVzZWQgKiBzaXplb2YoUkdCUVVBRCkpOwoKCQkvLyBDb3B5IHRoZSBiaXRtYXAKCQltZW1jcHkoRnJlZUltYWdlX0dldEJpdHMoX2RpYiksIGJpdHMsIEZyZWVJbWFnZV9HZXRQaXRjaChfZGliKSAqIEZyZWVJbWFnZV9HZXRIZWlnaHQoX2RpYikpOwoKCQlHbG9iYWxVbmxvY2sobHBWb2lkKTsKCgkJcmV0dXJuIFRSVUU7Cgl9CgoJcmV0dXJuIEZBTFNFOwp9CgpCT09MIGZpcFdpbkltYWdlOjpjb3B5RnJvbUJpdG1hcChIQklUTUFQIGhibXApIHsKCWlmKGhibXApIHsgCgkJaW50IFN1Y2Nlc3M7CiAgICAgICAgQklUTUFQIGJtOwoJCS8vIEdldCBpbmZvcm1hdGlvbnMgYWJvdXQgdGhlIGJpdG1hcAogICAgICAgIEdldE9iamVjdChoYm1wLCBzaXplb2YoQklUTUFQKSwgKExQU1RSKSAmYm0pOwoJCS8vIENyZWF0ZSB0aGUgaW1hZ2UKICAgICAgICBzZXRTaXplKEZJVF9CSVRNQVAsIChXT1JEKWJtLmJtV2lkdGgsIChXT1JEKWJtLmJtSGVpZ2h0LCAoV09SRClibS5ibUJpdHNQaXhlbCk7CgoJCS8vIFRoZSBHZXRESUJpdHMgZnVuY3Rpb24gY2xlYXJzIHRoZSBiaUNsclVzZWQgYW5kIGJpQ2xySW1wb3J0YW50IEJJVE1BUElORk8gbWVtYmVycyAoZG9udCd0IGtub3cgd2h5KSAKCQkvLyBTbyB3ZSBzYXZlIHRoZXNlIGluZm9zIGJlbG93LiBUaGlzIGlzIG5lZWRlZCBmb3IgcGFsZXR0aXplZCBpbWFnZXMgb25seS4gCgkJaW50IG5Db2xvcnMgPSBGcmVlSW1hZ2VfR2V0Q29sb3JzVXNlZChfZGliKTsKCgkJLy8gQ3JlYXRlIGEgZGV2aWNlIGNvbnRleHQgZm9yIHRoZSBiaXRtYXAKICAgICAgICBIREMgZGMgPSBHZXREQyhOVUxMKTsKCQkvLyBDb3B5IHRoZSBwaXhlbHMKCQlTdWNjZXNzID0gR2V0RElCaXRzKGRjLAkJCQkJCQkJLy8gaGFuZGxlIHRvIERDCgkJCQkJCQkJaGJtcCwJCQkJCQkvLyBoYW5kbGUgdG8gYml0bWFwCgkJCQkJCQkJMCwJCQkJCQkJLy8gZmlyc3Qgc2NhbiBsaW5lIHRvIHNldAoJCQkJCQkJCUZyZWVJbWFnZV9HZXRIZWlnaHQoX2RpYiksCS8vIG51bWJlciBvZiBzY2FuIGxpbmVzIHRvIGNvcHkKCQkJCQkJCQlGcmVlSW1hZ2VfR2V0Qml0cyhfZGliKSwJLy8gYXJyYXkgZm9yIGJpdG1hcCBiaXRzCgkJCQkJCQkJRnJlZUltYWdlX0dldEluZm8oX2RpYiksCS8vIGJpdG1hcCBkYXRhIGJ1ZmZlcgoJCQkJCQkJCURJQl9SR0JfQ09MT1JTCQkJCS8vIFJHQiAKCQkJCQkJCQkpOwoJCWlmKFN1Y2Nlc3MgPT0gMCkgewoJCQlGcmVlSW1hZ2VfT3V0cHV0TWVzc2FnZVByb2MoRklGX1VOS05PV04sICJFcnJvciA6IEdldERJQml0cyBmYWlsZWQiKTsKCQkJUmVsZWFzZURDKE5VTEwsIGRjKTsKCQkJcmV0dXJuIEZBTFNFOwogICAgICAgIH0KICAgICAgICBSZWxlYXNlREMoTlVMTCwgZGMpOwoKCQkvLyByZXN0b3JlIEJJVE1BUElORk8gbWVtYmVycwoJCQoJCUZyZWVJbWFnZV9HZXRJbmZvSGVhZGVyKF9kaWIpLT5iaUNsclVzZWQgPSBuQ29sb3JzOwoJCUZyZWVJbWFnZV9HZXRJbmZvSGVhZGVyKF9kaWIpLT5iaUNsckltcG9ydGFudCA9IG5Db2xvcnM7CgoJCXJldHVybiBUUlVFOwogICAgfQoKCXJldHVybiBGQUxTRTsKfQoKQk9PTCBmaXBXaW5JbWFnZTo6Y29weVRvQ2xpcGJvYXJkKEhXTkQgaFduZE5ld093bmVyKSBjb25zdCB7CglIQU5ETEUgaERJQiA9IGNvcHlUb0hhbmRsZSgpOwoKCWlmKE9wZW5DbGlwYm9hcmQoaFduZE5ld093bmVyKSkgewoJCWlmKEVtcHR5Q2xpcGJvYXJkKCkpIHsKCQkJaWYoU2V0Q2xpcGJvYXJkRGF0YShDRl9ESUIsIGhESUIpID09IE5VTEwpIHsKCQkJCU1lc3NhZ2VCb3goaFduZE5ld093bmVyLCAiVW5hYmxlIHRvIHNldCBDbGlwYm9hcmQgZGF0YSIsICJGcmVlSW1hZ2UiLCBNQl9JQ09ORVJST1IpOwoJCQkJQ2xvc2VDbGlwYm9hcmQoKTsKCQkJCXJldHVybiBGQUxTRTsKCQkJfQoJCX0KCX0KCUNsb3NlQ2xpcGJvYXJkKCk7CgoJcmV0dXJuIFRSVUU7Cn0KCkJPT0wgZmlwV2luSW1hZ2U6OnBhc3RlRnJvbUNsaXBib2FyZCgpIHsKCWlmKCFJc0NsaXBib2FyZEZvcm1hdEF2YWlsYWJsZShDRl9ESUIpKQoJCXJldHVybiBGQUxTRTsKCglpZihPcGVuQ2xpcGJvYXJkKE5VTEwpKSB7CgkJSEFORExFIGhESUIgPSBHZXRDbGlwYm9hcmREYXRhKENGX0RJQik7CgkJY29weUZyb21IYW5kbGUoaERJQik7CgkJQ2xvc2VDbGlwYm9hcmQoKTsKCQlyZXR1cm4gVFJVRTsKCX0KCUNsb3NlQ2xpcGJvYXJkKCk7CgoJcmV0dXJuIEZBTFNFOwp9CgovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vIFNjcmVlbiBjYXB0dXJlCgpCT09MIGZpcFdpbkltYWdlOjpjYXB0dXJlV2luZG93KEhXTkQgaFduZEFwcGxpY2F0aW9uV2luZG93LCBIV05EIGhXbmRTZWxlY3RlZFdpbmRvdykgewoJaW50IHhTY3JlZW4sIHlTY3JlZW4sIHhzaGlmdCwgeXNoaWZ0OwoJUkVDVCByOwoKCS8vIEdldCB3aW5kb3cgc2l6ZQoJR2V0V2luZG93UmVjdChoV25kU2VsZWN0ZWRXaW5kb3csICZyKTsKCgkvLyBDaGVjayBpZiB0aGUgd2luZG93IGlzIG91dCBvZiB0aGUgc2NyZWVuIG9yIG1heGltaXhlZAoJeHNoaWZ0ID0gMDsKCXlzaGlmdCA9IDA7Cgl4U2NyZWVuID0gR2V0U3lzdGVtTWV0cmljcyhTTV9DWFNDUkVFTik7Cgl5U2NyZWVuID0gR2V0U3lzdGVtTWV0cmljcyhTTV9DWVNDUkVFTik7CglpZihyLnJpZ2h0ID4geFNjcmVlbikKCQkgICByLnJpZ2h0ID0geFNjcmVlbjsKCWlmKHIuYm90dG9tID4geVNjcmVlbikKCQkgICByLmJvdHRvbSA9IHlTY3JlZW47CglpZihyLmxlZnQgPCAwKSB7CgkJICAgeHNoaWZ0ID0gLXIubGVmdDsKCQkgICByLmxlZnQgPSAwOwoJfQoJaWYoci50b3AgPCAwKXsKCQkgICB5c2hpZnQgPSAtci50b3A7CgkJICAgci50b3AgPSAwOwoJfQoJCglpbnQgd2lkdGggID0gci5yaWdodCAgLSByLmxlZnQ7CglpbnQgaGVpZ2h0ID0gci5ib3R0b20gLSByLnRvcDsKCglpZih3aWR0aCA8PSAwIHx8IGhlaWdodCA8PSAwKQoJCXJldHVybiBGQUxTRTsKCgkvLyBIaWRlIHRoZSBhcHBsaWNhdGlvbiB3aW5kb3cuIAoJU2hvd1dpbmRvdyhoV25kQXBwbGljYXRpb25XaW5kb3csIFNXX0hJREUpOyAKCS8vIEJyaW5nIHRoZSB3aW5kb3cgYXQgdGhlIHRvcCBtb3N0IGxldmVsCglTZXRXaW5kb3dQb3MoaFduZFNlbGVjdGVkV2luZG93LCBIV05EX1RPUE1PU1QsIDAsIDAsIDAsIDAsIFNXUF9OT01PVkV8U1dQX05PU0laRSk7CgkvLyBHaXZlIGVub3VnaCB0aW1lIHRvIHJlZnJlc2ggdGhlIHdpbmRvdwoJU2xlZXAoNTAwKTsKCgkvLyBQcmVwYXJlIHRoZSBEQ3MKCUhEQyBkc3REQyA9IEdldERDKE5VTEwpOwogICAgSERDIHNyY0RDID0gR2V0V2luZG93REMoaFduZFNlbGVjdGVkV2luZG93KTsgLy8gZnVsbCB3aW5kb3cgKEdldERDKGhXbmRTZWxlY3RlZFdpbmRvdykgPSBjbGllbnRhcmVhKQoJSERDIG1lbURDID0gQ3JlYXRlQ29tcGF0aWJsZURDKGRzdERDKTsKCQoJLy8gQ29weSB0aGUgc2NyZWVuIHRvIHRoZSBiaXRtYXAKCUhCSVRNQVAgYm0gPSBDcmVhdGVDb21wYXRpYmxlQml0bWFwKGRzdERDLCB3aWR0aCwgaGVpZ2h0KTsKCUhCSVRNQVAgb2xkYm0gPSAoSEJJVE1BUClTZWxlY3RPYmplY3QobWVtREMsIGJtKTsKCUJpdEJsdChtZW1EQywgMCwgMCwgd2lkdGgsIGhlaWdodCwgc3JjREMsIHhzaGlmdCwgeXNoaWZ0LCBTUkNDT1BZKTsKCgkvLyBSZWRyYXcgdGhlIGFwcGxpY2F0aW9uIHdpbmRvdy4gCglTaG93V2luZG93KGhXbmRBcHBsaWNhdGlvbldpbmRvdywgU1dfU0hPVyk7IAoKCS8vIFJlc3RvcmUgdGhlIHBvc2l0aW9uCglTZXRXaW5kb3dQb3MoaFduZFNlbGVjdGVkV2luZG93LCBIV05EX05PVE9QTU9TVCwgMCwgMCwgMCwgMCwgU1dQX05PTU9WRXxTV1BfTk9TSVpFKTsKCVNldFdpbmRvd1BvcyhoV25kQXBwbGljYXRpb25XaW5kb3csIEhXTkRfVE9QLCAwLCAwLCAwLCAwLCBTV1BfTk9NT1ZFfFNXUF9OT1NJWkUpOwoJCgkvLyBDb252ZXJ0IHRoZSBIQklUTUFQIHRvIGEgRklCSVRNQVAKCWNvcHlGcm9tQml0bWFwKGJtKTsKCgkvLyBGcmVlIG9iamVjdHMKCURlbGV0ZU9iamVjdChTZWxlY3RPYmplY3QobWVtREMsIG9sZGJtKSk7CglEZWxldGVEQyhtZW1EQyk7CgoJLy8gQ29udmVydCAzMi1iaXQgaW1hZ2VzIHRvIDI0LWJpdAoJaWYoZ2V0Qml0c1BlclBpeGVsKCkgPT0gMzIpIHsKCQljb252ZXJ0VG8yNEJpdHMoKTsKCX0KCglyZXR1cm4gVFJVRTsKfQoKCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8gUGFpbnRpbmcgb3BlcmF0aW9ucwoKdm9pZCBmaXBXaW5JbWFnZTo6ZHJhd0V4KEhEQyBoREMsIFJFQ1QmIHJjRGVzdCwgQk9PTCB1c2VGaWxlQmtnLCBSR0JRVUFEICphcHBCa0NvbG9yLCBGSUJJVE1BUCAqYmcpIGNvbnN0IHsKCS8vIENvbnZlcnQgdG8gYSBzdGFuZGFyZCBiaXRtYXAgaWYgbmVlZGVkCglpZihfYkhhc0NoYW5nZWQpIHsKCQlpZihfYkRlbGV0ZU1lKSB7CgkJCUZyZWVJbWFnZV9VbmxvYWQoX2Rpc3BsYXlfZGliKTsKCQkJX2Rpc3BsYXlfZGliID0gTlVMTDsKCQkJX2JEZWxldGVNZSA9IEZBTFNFOwoJCX0KCgkJRlJFRV9JTUFHRV9UWVBFIGltYWdlX3R5cGUgPSBnZXRJbWFnZVR5cGUoKTsKCQlpZihpbWFnZV90eXBlID09IEZJVF9CSVRNQVApIHsKCQkJQk9PTCBiSGFzQmFja2dyb3VuZCA9IEZyZWVJbWFnZV9IYXNCYWNrZ3JvdW5kQ29sb3IoX2RpYik7CgkJCUJPT0wgYklzVHJhbnNwYXJlbnQgPSBGcmVlSW1hZ2VfSXNUcmFuc3BhcmVudChfZGliKTsKCgkJCWlmKCFiSXNUcmFuc3BhcmVudCAmJiAoIWJIYXNCYWNrZ3JvdW5kIHx8ICF1c2VGaWxlQmtnKSkgewoJCQkJLy8gQ29weSBwb2ludGVyCgkJCQlfZGlzcGxheV9kaWIgPSBfZGliOwoJCQl9CgkJCWVsc2UgewoJCQkJLy8gQ3JlYXRlIHRoZSB0cmFuc3BhcmVudCAvIGFscGhhIGJsZW5kZWQgaW1hZ2UKCQkJCV9kaXNwbGF5X2RpYiA9IEZyZWVJbWFnZV9Db21wb3NpdGUoX2RpYiwgdXNlRmlsZUJrZywgYXBwQmtDb2xvciwgYmcpOwoJCQkJaWYoX2Rpc3BsYXlfZGliKSB7CgkJCQkJLy8gUmVtZW1iZXIgdG8gZGVsZXRlIF9kaXNwbGF5X2RpYgoJCQkJCV9iRGVsZXRlTWUgPSBUUlVFOwoJCQkJfSBlbHNlIHsKCQkJCQkvLyBTb21ldGhpbmcgZmFpbGVkOiBjb3B5IHBvaW50ZXJzCgkJCQkJX2Rpc3BsYXlfZGliID0gX2RpYjsKCQkJCX0KCQkJfQoJCX0gZWxzZSB7CgkJCS8vIENvbnZlcnQgdG8gYSBzdGFuZGFyZCBkaWIgZm9yIGRpc3BsYXkKCgkJCWlmKGltYWdlX3R5cGUgPT0gRklUX0NPTVBMRVgpIHsKCQkJCS8vIENvbnZlcnQgdG8gdHlwZSBGSVRfRE9VQkxFCgkJCQlGSUJJVE1BUCAqZGliX2RvdWJsZSA9IEZyZWVJbWFnZV9HZXRDb21wbGV4Q2hhbm5lbChfZGliLCBGSUNDX01BRyk7CgkJCQkvLyBDb252ZXJ0IHRvIGEgc3RhbmRhcmQgYml0bWFwIChsaW5lYXIgc2NhbGluZykKCQkJCV9kaXNwbGF5X2RpYiA9IEZyZWVJbWFnZV9Db252ZXJ0VG9TdGFuZGFyZFR5cGUoZGliX2RvdWJsZSwgVFJVRSk7CgkJCQkvLyBGcmVlIGltYWdlIG9mIHR5cGUgRklUX0RPVUJMRQoJCQkJRnJlZUltYWdlX1VubG9hZChkaWJfZG91YmxlKTsKCQkJfSBlbHNlIGlmKChpbWFnZV90eXBlID09IEZJVF9SR0JGKSB8fCAoaW1hZ2VfdHlwZSA9PSBGSVRfUkdCQUYpIHx8IChpbWFnZV90eXBlID09IEZJVF9SR0IxNikpIHsKCQkJCS8vIEFwcGx5IGEgdG9uZSBtYXBwaW5nIGFsZ29yaXRobSBhbmQgY29udmVydCB0byAyNC1iaXQgCgkJCQlzd2l0Y2goX3RtbykgewoJCQkJCWNhc2UgRklUTU9fUkVJTkhBUkQwNToKCQkJCQkJX2Rpc3BsYXlfZGliID0gRnJlZUltYWdlX1Rtb1JlaW5oYXJkMDVFeChfZGliLCBfdG1vX3BhcmFtXzEsIF90bW9fcGFyYW1fMiwgX3Rtb19wYXJhbV8zLCBfdG1vX3BhcmFtXzQpOwoJCQkJCQlicmVhazsKCQkJCQlkZWZhdWx0OgoJCQkJCQlfZGlzcGxheV9kaWIgPSBGcmVlSW1hZ2VfVG9uZU1hcHBpbmcoX2RpYiwgX3RtbywgX3Rtb19wYXJhbV8xLCBfdG1vX3BhcmFtXzIpOwoJCQkJCQlicmVhazsKCQkJCX0KCQkJfSBlbHNlIGlmKGltYWdlX3R5cGUgPT0gRklUX1JHQkExNikgewoJCQkJLy8gQ29udmVydCB0byAzMi1iaXQKCQkJCUZJQklUTUFQICpkaWIzMiA9IEZyZWVJbWFnZV9Db252ZXJ0VG8zMkJpdHMoX2RpYik7CgkJCQlpZihkaWIzMikgewoJCQkJCS8vIENyZWF0ZSB0aGUgdHJhbnNwYXJlbnQgLyBhbHBoYSBibGVuZGVkIGltYWdlCgkJCQkJX2Rpc3BsYXlfZGliID0gRnJlZUltYWdlX0NvbXBvc2l0ZShkaWIzMiwgdXNlRmlsZUJrZywgYXBwQmtDb2xvciwgYmcpOwoJCQkJCUZyZWVJbWFnZV9VbmxvYWQoZGliMzIpOwoJCQkJfQoJCQl9IGVsc2UgewoJCQkJLy8gT3RoZXIgY2FzZXM6IGNvbnZlcnQgdG8gYSBzdGFuZGFyZCBiaXRtYXAgKGxpbmVhciBzY2FsaW5nKQoJCQkJX2Rpc3BsYXlfZGliID0gRnJlZUltYWdlX0NvbnZlcnRUb1N0YW5kYXJkVHlwZShfZGliLCBUUlVFKTsKCQkJfQoJCQkvLyBSZW1lbWJlciB0byBkZWxldGUgX2Rpc3BsYXlfZGliCgkJCV9iRGVsZXRlTWUgPSBUUlVFOwoJCX0KCgkJX2JIYXNDaGFuZ2VkID0gRkFMU0U7Cgl9CgoJLy8gRHJhdyB0aGUgZGliCglTZXRTdHJldGNoQmx0TW9kZShoREMsIENPTE9ST05DT0xPUik7CQoJU3RyZXRjaERJQml0cyhoREMsIHJjRGVzdC5sZWZ0LCByY0Rlc3QudG9wLCAKCQlyY0Rlc3QucmlnaHQtcmNEZXN0LmxlZnQsIHJjRGVzdC5ib3R0b20tcmNEZXN0LnRvcCwgCgkJMCwgMCwgRnJlZUltYWdlX0dldFdpZHRoKF9kaXNwbGF5X2RpYiksIEZyZWVJbWFnZV9HZXRIZWlnaHQoX2Rpc3BsYXlfZGliKSwKCQlGcmVlSW1hZ2VfR2V0Qml0cyhfZGlzcGxheV9kaWIpLCBGcmVlSW1hZ2VfR2V0SW5mbyhfZGlzcGxheV9kaWIpLCBESUJfUkdCX0NPTE9SUywgU1JDQ09QWSk7Cgp9Cgp2b2lkIGZpcFdpbkltYWdlOjpzZXRUb25lTWFwcGluZ09wZXJhdG9yKEZSRUVfSU1BR0VfVE1PIHRtbywgZG91YmxlIGZpcnN0X3BhcmFtLCBkb3VibGUgc2Vjb25kX3BhcmFtLCBkb3VibGUgdGhpcmRfcGFyYW0sIGRvdWJsZSBmb3VydGhfcGFyYW0pIHsKCS8vIGF2b2lkIGNvc3RseSBvcGVyYXRpb25zIGlmIHBvc3NpYmxlIC4uLgoJaWYoKF90bW8gIT0gdG1vKSB8fCAoX3Rtb19wYXJhbV8xICE9IGZpcnN0X3BhcmFtKSB8fCAoX3Rtb19wYXJhbV8yICE9IHNlY29uZF9wYXJhbSkgfHwgKF90bW9fcGFyYW1fMyAhPSB0aGlyZF9wYXJhbSkgfHwgKF90bW9fcGFyYW1fNCAhPSBmb3VydGhfcGFyYW0pKSB7CgkJX3RtbyA9IHRtbzsKCQlfdG1vX3BhcmFtXzEgPSBmaXJzdF9wYXJhbTsKCQlfdG1vX3BhcmFtXzIgPSBzZWNvbmRfcGFyYW07CgkJX3Rtb19wYXJhbV8zID0gdGhpcmRfcGFyYW07CgkJX3Rtb19wYXJhbV80ID0gZm91cnRoX3BhcmFtOwoKCQlGUkVFX0lNQUdFX1RZUEUgaW1hZ2VfdHlwZSA9IGdldEltYWdlVHlwZSgpOwoJCXN3aXRjaChpbWFnZV90eXBlKSB7CgkJCWNhc2UgRklUX1JHQkY6CgkJCWNhc2UgRklUX1JHQkFGOgoJCQljYXNlIEZJVF9SR0IxNjoKCQkJY2FzZSBGSVRfUkdCQTE2OgoJCQkJX2JIYXNDaGFuZ2VkID0gVFJVRTsKCQkJCWJyZWFrOwoJCQlkZWZhdWx0OgoJCQkJYnJlYWs7CgkJfQoJfQp9Cgp2b2lkIGZpcFdpbkltYWdlOjpnZXRUb25lTWFwcGluZ09wZXJhdG9yKEZSRUVfSU1BR0VfVE1PICp0bW8sIGRvdWJsZSAqZmlyc3RfcGFyYW0sIGRvdWJsZSAqc2Vjb25kX3BhcmFtLCBkb3VibGUgKnRoaXJkX3BhcmFtLCBkb3VibGUgKmZvdXJ0aF9wYXJhbSkgY29uc3QgewoJKnRtbyA9IF90bW87CgkqZmlyc3RfcGFyYW0gPSBfdG1vX3BhcmFtXzE7Cgkqc2Vjb25kX3BhcmFtID0gX3Rtb19wYXJhbV8yOwoJKnRoaXJkX3BhcmFtID0gX3Rtb19wYXJhbV8zOwoJKmZvdXJ0aF9wYXJhbSA9IF90bW9fcGFyYW1fNDsKfQoKCiNlbmRpZiAvLyBfV0lOMzIK