LyoKICogIHJlYWRwcm9maWxlLmMgLSB1c2VkIHRvIHJlYWQgL3Byb2MvcHJvZmlsZQogKgogKiAgQ29weXJpZ2h0IChDKSAxOTk0LDE5OTYgQWxlc3NhbmRybyBSdWJpbmkgKHJ1YmluaUBpcHZ2aXMudW5pcHYuaXQpCiAqCiAqICAgVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKICogICBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQogKiAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCiAqICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogICBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiAgIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKICogICBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCiAqICAgYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogICBGb3VuZGF0aW9uLCBJbmMuLCA2NzUgTWFzcyBBdmUsIENhbWJyaWRnZSwgTUEgMDIxMzksIFVTQS4KICovCgovKgogKiAxOTk5LTAyLTIyIEFya2FkaXVzeiBNabZraWV3aWN6IDxtaXNpZWtAcGxkLk9SRy5QTD4KICogLSBhZGRlZCBOYXRpdmUgTGFuZ3VhZ2UgU3VwcG9ydAogKiAxOTk5LTA5LTAxIFN0ZXBoYW5lIEVyYW5pYW4gPGVyYW5pYW5AY2VsbG8uaHBsLmhwLmNvbT4KICogLSA2NGJpdCBjbGVhbiBwYXRjaAogKiAzRmViMjAwMSBBbmRyZXcgTW9ydG9uIDxhbmRyZXdtQHVvdy5lZHUuYXU+CiAqIC0gLU0gb3B0aW9uIHRvIHdyaXRlIHByb2ZpbGUgbXVsdGlwbGllci4KICogMjAwMS0xMS0wNyBXZXJuZXIgQWxtZXNiZXJnZXIgPHdhQGFsbWVzYmVyZ2VyLm5ldD4KICogLSBieXRlIG9yZGVyIGF1dG8tZGV0ZWN0aW9uIGFuZCAtbiBvcHRpb24KICogMjAwMS0xMS0wOSBXZXJuZXIgQWxtZXNiZXJnZXIgPHdhQGFsbWVzYmVyZ2VyLm5ldD4KICogLSBza2lwIHN0ZXAgc2l6ZSAoaW5kZXggMCkKICogMjAwMi0wMy0wOSBKb2huIExldm9uIDxtb3pAY29tcHNvYy5tYW4uYWMudWs+CiAqIC0gbWFrZSBtYXBsaW5lbm8gZG8gc29tZXRoaW5nCiAqIDIwMDItMTEtMjggTWFkcyBNYXJ0aW4gSm9lcmdlbnNlbiArCiAqIC0gYWxzbyB0cnkgL2Jvb3QvU3lzdGVtLm1hcC1gdW5hbWUgLXJgCiAqIDIwMDMtMDQtMDkgV2VybmVyIEFsbWVzYmVyZ2VyIDx3YUBhbG1lc2Jlcmdlci5uZXQ+CiAqIC0gZml4ZWQgb2ZmLWJ5IGVpZ2h0IGVycm9yIGFuZCBpbXByb3ZlZCBoZXVyaXN0aWNzIGluIGJ5dGUgb3JkZXIgZGV0ZWN0aW9uCiAqIDIwMDMtMDgtMTIgTmlraXRhIERhbmlsb3YgPE5pa2l0YUBOYW1lc3lzLkNPTT4KICogLSBhZGRlZCAtcyBvcHRpb247IGV4YW1wbGUgb2YgdXNlOgogKiAicmVhZHByb2ZpbGUgLXMgLW0gL2Jvb3QvU3lzdGVtLm1hcC10ZXN0IHwgZ3JlcCBfX2RfbG9va3VwIHwgc29ydCAtbiAtazMiCiAqCiAqIFRha2VuIGZyb20gdXRpbC1saW51eCBhbmQgYWRhcHRlZCBmb3IgYnVzeWJveCBieQogKiBQYXVsIE11bmR0IDxsZXRoYWxAbGludXgtc2gub3JnPi4KICovCgojaW5jbHVkZSA8ZXJybm8uaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxmY250bC5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDx1bmlzdGQuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8c3lzL3R5cGVzLmg+CiNpbmNsdWRlIDxzeXMvc3RhdC5oPgojaW5jbHVkZSA8c3lzL3V0c25hbWUuaD4KCiNpbmNsdWRlICJidXN5Ym94LmgiCgojZGVmaW5lIFNfTEVOIDEyOAoKLyogVGhlc2UgYXJlIHRoZSBkZWZhdWx0cyAqLwpzdGF0aWMgY2hhciBkZWZhdWx0bWFwW109Ii9ib290L1N5c3RlbS5tYXAiOwpzdGF0aWMgY2hhciBkZWZhdWx0cHJvW109Ii9wcm9jL3Byb2ZpbGUiOwoKaW50IHJlYWRwcm9maWxlX21haW4oaW50IGFyZ2MsIGNoYXIgKiphcmd2KQp7CglGSUxFICptYXA7CglpbnQgcHJvRmQ7CgljaGFyICptYXBGaWxlLCAqcHJvRmlsZSwgKm11bHQ9MDsKCXVuc2lnbmVkIGxvbmcgbGVuPTAsIGluZHg9MTsKCXVuc2lnbmVkIGxvbmcgbG9uZyBhZGQwPTA7Cgl1bnNpZ25lZCBpbnQgc3RlcDsKCXVuc2lnbmVkIGludCAqYnVmLCB0b3RhbCwgZm5fbGVuOwoJdW5zaWduZWQgbG9uZyBsb25nIGZuX2FkZCwgbmV4dF9hZGQ7ICAgICAgICAgIC8qIGN1cnJlbnQgYW5kIG5leHQgYWRkcmVzcyAqLwoJY2hhciBmbl9uYW1lW1NfTEVOXSwgbmV4dF9uYW1lW1NfTEVOXTsgICAvKiBjdXJyZW50IGFuZCBuZXh0IG5hbWUgKi8KCWNoYXIgbW9kZVs4XTsKCWludCBjOwoJaW50IG9wdEFsbD0wLCBvcHRJbmZvPTAsIG9wdFJlc2V0PTAsIG9wdFZlcmJvc2U9MCwgb3B0TmF0aXZlPTA7CglpbnQgb3B0Qmlucz0wLCBvcHRTdWI9MDsKCWNoYXIgbWFwbGluZVtTX0xFTl07CglpbnQgbWFwbGluZW5vPTE7CglpbnQgaGVhZGVyX3ByaW50ZWQ7CgojZGVmaW5lIG5leHQgKGN1cnJlbnReMSkKCglwcm9GaWxlID0gZGVmYXVsdHBybzsKCW1hcEZpbGUgPSBkZWZhdWx0bWFwOwoKCXdoaWxlICgoYyA9IGdldG9wdChhcmdjLCBhcmd2LCAiTTptOm5wOml0dmFyVmJzIikpICE9IC0xKSB7CgkJc3dpdGNoKGMpIHsKCQljYXNlICdtJzoKCQkJbWFwRmlsZSA9IG9wdGFyZzsKCQkJYnJlYWs7CgkJY2FzZSAnbic6CgkJCW9wdE5hdGl2ZSsrOwoJCQlicmVhazsKCQljYXNlICdwJzoKCQkJcHJvRmlsZSA9IG9wdGFyZzsKCQkJYnJlYWs7CgkJY2FzZSAnYSc6CgkJCW9wdEFsbCsrOwoJCQlicmVhazsKCQljYXNlICdiJzoKCQkJb3B0QmlucysrOwoJCQlicmVhazsKCQljYXNlICdzJzoKCQkJb3B0U3ViKys7CgkJCWJyZWFrOwoJCWNhc2UgJ2knOgoJCQlvcHRJbmZvKys7CgkJCWJyZWFrOwoJCWNhc2UgJ00nOgoJCQltdWx0ID0gb3B0YXJnOwoJCQlicmVhazsKCQljYXNlICdyJzoKCQkJb3B0UmVzZXQrKzsKCQkJYnJlYWs7CgkJY2FzZSAndic6CgkJCW9wdFZlcmJvc2UrKzsKCQkJYnJlYWs7CgkJZGVmYXVsdDoKCQkJYmJfc2hvd191c2FnZSgpOwoJCX0KCX0KCglpZiAob3B0UmVzZXQgfHwgbXVsdCkgewoJCWludCBtdWx0aXBsaWVyLCBmZCwgdG9fd3JpdGU7CgoJCS8qCgkJICogV2hlbiB3cml0aW5nIHRoZSBtdWx0aXBsaWVyLCBpZiB0aGUgbGVuZ3RoIG9mIHRoZSB3cml0ZSBpcwoJCSAqIG5vdCBzaXplb2YoaW50KSwgdGhlIG11bHRpcGxpZXIgaXMgbm90IGNoYW5nZWQKCQkgKi8KCQlpZiAobXVsdCkgewoJCQltdWx0aXBsaWVyID0gc3RydG91bChtdWx0LCAwLCAxMCk7CgkJCXRvX3dyaXRlID0gc2l6ZW9mKGludCk7CgkJfSBlbHNlIHsKCQkJbXVsdGlwbGllciA9IDA7CgkJCXRvX3dyaXRlID0gMTsJLyogc3RoIGRpZmZlcmVudCBmcm9tIHNpemVvZihpbnQpICovCgkJfQoKCQlmZCA9IGJiX3hvcGVuKGRlZmF1bHRwcm8sT19XUk9OTFkpOwoJCWlmIChmZCA8IDApCgkJCWJiX3BlcnJvcl9tc2dfYW5kX2RpZShkZWZhdWx0cHJvKTsKCgkJaWYgKHdyaXRlKGZkLCAmbXVsdGlwbGllciwgdG9fd3JpdGUpICE9IHRvX3dyaXRlKQoJCQliYl9wZXJyb3JfbXNnX2FuZF9kaWUoImVycm9yIHdyaXRpbmcgJXMiLCBkZWZhdWx0cHJvKTsKCgkJY2xvc2UoZmQpOwoJCXJldHVybiBFWElUX1NVQ0NFU1M7Cgl9CgoJLyoKCSAqIFVzZSBhbiBmZCBmb3IgdGhlIHByb2ZpbGluZyBidWZmZXIsIHRvIHNraXAgc3RkaW8gb3ZlcmhlYWQKCSAqLwoJaWYgKCgocHJvRmQgPSBiYl94b3Blbihwcm9GaWxlLE9fUkRPTkxZKSkgPCAwKQoJICAgIHx8ICgoaW50KShsZW49bHNlZWsocHJvRmQsMCxTRUVLX0VORCkpIDwgMCkKCSAgICB8fCAobHNlZWsocHJvRmQsMCxTRUVLX1NFVCkgPCAwKSkKCQliYl9wZXJyb3JfbXNnX2FuZF9kaWUocHJvRmlsZSk7CgoJaWYgKCEoYnVmID0geG1hbGxvYyhsZW4pKSkKCQliYl9wZXJyb3Jfbm9tc2dfYW5kX2RpZSgpOwoKCWlmIChyZWFkKHByb0ZkLGJ1ZixsZW4pICE9IGxlbikKCQliYl9wZXJyb3JfbXNnX2FuZF9kaWUocHJvRmlsZSk7CgoJY2xvc2UocHJvRmQpOwoKCWlmICghb3B0TmF0aXZlKSB7CgkJaW50IGVudHJpZXMgPSBsZW4vc2l6ZW9mKCpidWYpOwoJCWludCBiaWcgPSAwLHNtYWxsID0gMCxpOwoJCXVuc2lnbmVkICpwOwoKCQlmb3IgKHAgPSBidWYrMTsgcCA8IGJ1ZitlbnRyaWVzOyBwKyspIHsKCQkJaWYgKCpwICYgfjBVIDw8IChzaXplb2YoKmJ1ZikqNCkpCgkJCQliaWcrKzsKCQkJaWYgKCpwICYgKCgxIDw8IChzaXplb2YoKmJ1ZikqNCkpLTEpKQoJCQkJc21hbGwrKzsKCQl9CgkJaWYgKGJpZyA+IHNtYWxsKSB7CgkJCWZwcmludGYoc3RkZXJyLCJBc3N1bWluZyByZXZlcnNlZCBieXRlIG9yZGVyLiAiCgkJCQkiVXNlIC1uIHRvIGZvcmNlIG5hdGl2ZSBieXRlIG9yZGVyLlxuIik7CgkJCWZvciAocCA9IGJ1ZjsgcCA8IGJ1ZitlbnRyaWVzOyBwKyspCgkJCQlmb3IgKGkgPSAwOyBpIDwgc2l6ZW9mKCpidWYpLzI7IGkrKykgewoJCQkJCXVuc2lnbmVkIGNoYXIgKmIgPSAodW5zaWduZWQgY2hhciAqKSBwOwoJCQkJCXVuc2lnbmVkIGNoYXIgdG1wOwoKCQkJCQl0bXAgPSBiW2ldOwoJCQkJCWJbaV0gPSBiW3NpemVvZigqYnVmKS1pLTFdOwoJCQkJCWJbc2l6ZW9mKCpidWYpLWktMV0gPSB0bXA7CgkJCQl9CgkJfQoJfQoKCXN0ZXAgPSBidWZbMF07CglpZiAob3B0SW5mbykgewoJCXByaW50ZigiU2FtcGxpbmdfc3RlcDogJWlcbiIsIHN0ZXApOwoJCXJldHVybiBFWElUX1NVQ0NFU1M7Cgl9CgoJdG90YWwgPSAwOwoKCW1hcCA9IGJiX3hmb3BlbihtYXBGaWxlLCAiciIpOwoJaWYgKG1hcCA9PSBOVUxMKQoJCWJiX3BlcnJvcl9tc2dfYW5kX2RpZShtYXBGaWxlKTsKCgl3aGlsZSAoZmdldHMobWFwbGluZSxTX0xFTixtYXApKSB7CgkJaWYgKHNzY2FuZihtYXBsaW5lLCIlbGx4ICVzICVzIiwmZm5fYWRkLG1vZGUsZm5fbmFtZSkgIT0gMykKCQkJYmJfZXJyb3JfbXNnX2FuZF9kaWUoIiVzKCVpKTogd3JvbmcgbWFwIGxpbmUiLAoJCQkJCSAgICAgbWFwRmlsZSwgbWFwbGluZW5vKTsKCgkJaWYgKCFzdHJjbXAoZm5fbmFtZSwiX3N0ZXh0IikpIC8qIG9ubHkgZWxmIHdvcmtzIGxpa2UgdGhpcyAqLyB7CgkJCWFkZDAgPSBmbl9hZGQ7CgkJCWJyZWFrOwoJCX0KCQltYXBsaW5lbm8rKzsKCX0KCglpZiAoIWFkZDApCgkJYmJfZXJyb3JfbXNnX2FuZF9kaWUoImNhbid0IGZpbmQgXCJfc3RleHRcIiBpbiAlc1xuIiwgbWFwRmlsZSk7CgoJLyoKCSAqIE1haW4gbG9vcC4KCSAqLwoJd2hpbGUgKGZnZXRzKG1hcGxpbmUsU19MRU4sbWFwKSkgewoJCXVuc2lnbmVkIGludCB0aGlzID0gMDsKCgkJaWYgKHNzY2FuZihtYXBsaW5lLCIlbGx4ICVzICVzIiwmbmV4dF9hZGQsbW9kZSxuZXh0X25hbWUpICE9IDMpCgkJCWJiX2Vycm9yX21zZ19hbmRfZGllKCIlcyglaSk6IHdyb25nIG1hcCBsaW5lXG4iLAoJCQkJCSAgICAgbWFwRmlsZSwgbWFwbGluZW5vKTsKCgkJaGVhZGVyX3ByaW50ZWQgPSAwOwoKCQkvKiBpZ25vcmUgYW55IExFQURJTkcgKGJlZm9yZSBhICdbdFRdJyBzeW1ib2wgaXMgZm91bmQpCgkJICAgQWJzb2x1dGUgc3ltYm9scyAqLwoJCWlmICgoKm1vZGUgPT0gJ0EnIHx8ICptb2RlID09ICc/JykgJiYgdG90YWwgPT0gMCkgY29udGludWU7CgkJaWYgKCptb2RlICE9ICdUJyAmJiAqbW9kZSAhPSAndCcgJiYKCQkgICAgKm1vZGUgIT0gJ1cnICYmICptb2RlICE9ICd3JykKCQkJYnJlYWs7CS8qIG9ubHkgdGV4dCBpcyBwcm9maWxlZCAqLwoKCQlpZiAoaW5keCA+PSBsZW4gLyBzaXplb2YoKmJ1ZikpCgkJCWJiX2Vycm9yX21zZ19hbmRfZGllKCJwcm9maWxlIGFkZHJlc3Mgb3V0IG9mIHJhbmdlLiAiCgkJCQkJICAgICAiV3JvbmcgbWFwIGZpbGU/Iik7CgoJCXdoaWxlIChpbmR4IDwgKG5leHRfYWRkLWFkZDApL3N0ZXApIHsKCQkJaWYgKG9wdEJpbnMgJiYgKGJ1ZltpbmR4XSB8fCBvcHRBbGwpKSB7CgkJCQlpZiAoIWhlYWRlcl9wcmludGVkKSB7CgkJCQkJcHJpbnRmICgiJXM6XG4iLCBmbl9uYW1lKTsKCQkJCQloZWFkZXJfcHJpbnRlZCA9IDE7CgkJCQl9CgkJCQlwcmludGYgKCJcdCVsbHhcdCV1XG4iLCAoaW5keCAtIDEpKnN0ZXAgKyBhZGQwLCBidWZbaW5keF0pOwoJCQl9CgkJCXRoaXMgKz0gYnVmW2luZHgrK107CgkJfQoJCXRvdGFsICs9IHRoaXM7CgoJCWlmIChvcHRCaW5zKSB7CgkJCWlmIChvcHRWZXJib3NlIHx8IHRoaXMgPiAwKQoJCQkJcHJpbnRmICgiICB0b3RhbFx0XHRcdFx0JXVcbiIsIHRoaXMpOwoJCX0gZWxzZSBpZiAoKHRoaXMgfHwgb3B0QWxsKSAmJgoJCQkgICAoZm5fbGVuID0gbmV4dF9hZGQtZm5fYWRkKSAhPSAwKSB7CgkJCWlmIChvcHRWZXJib3NlKQoJCQkJcHJpbnRmKCIlMDE2bGx4ICUtNDBzICU2aSAlOC40ZlxuIiwgZm5fYWRkLAoJCQkJICAgICAgIGZuX25hbWUsdGhpcyx0aGlzLyhkb3VibGUpZm5fbGVuKTsKCQkJZWxzZQoJCQkJcHJpbnRmKCIlNmkgJS00MHMgJTguNGZcbiIsCgkJCQkgICAgICAgdGhpcyxmbl9uYW1lLHRoaXMvKGRvdWJsZSlmbl9sZW4pOwoJCQlpZiAob3B0U3ViKSB7CgkJCQl1bnNpZ25lZCBsb25nIGxvbmcgc2NhbjsKCgkJCQlmb3IgKHNjYW4gPSAoZm5fYWRkLWFkZDApL3N0ZXAgKyAxOwoJCQkJICAgICBzY2FuIDwgKG5leHRfYWRkLWFkZDApL3N0ZXA7IHNjYW4rKykgewoJCQkJCXVuc2lnbmVkIGxvbmcgbG9uZyBhZGRyOwoKCQkJCQlhZGRyID0gKHNjYW4gLSAxKSpzdGVwICsgYWRkMDsKCQkJCQlwcmludGYoIlx0JSNsbHhcdCVzKyUjbGx4XHQldVxuIiwKCQkJCQkgICAgICAgYWRkciwgZm5fbmFtZSwgYWRkciAtIGZuX2FkZCwKCQkJCQkgICAgICAgYnVmW3NjYW5dKTsKCQkJCX0KCQkJfQoJCX0KCgkJZm5fYWRkID0gbmV4dF9hZGQ7CgkJc3RyY3B5KGZuX25hbWUsbmV4dF9uYW1lKTsKCgkJbWFwbGluZW5vKys7Cgl9CgoJLyogY2xvY2sgdGlja3MsIG91dCBvZiBrZXJuZWwgdGV4dCAtIHByb2JhYmx5IG1vZHVsZXMgKi8KCXByaW50ZigiJTZpICVzXG4iLCBidWZbbGVuL3NpemVvZigqYnVmKS0xXSwgIip1bmtub3duKiIpOwoKCS8qIHRyYWlsZXIgKi8KCWlmIChvcHRWZXJib3NlKQoJCXByaW50ZigiJTAxNnggJS00MHMgJTZpICU4LjRmXG4iLAoJCSAgICAgICAwLCJ0b3RhbCIsdG90YWwsdG90YWwvKGRvdWJsZSkoZm5fYWRkLWFkZDApKTsKCWVsc2UKCQlwcmludGYoIiU2aSAlLTQwcyAlOC40ZlxuIiwKCQkgICAgICAgdG90YWwsInRvdGFsIix0b3RhbC8oZG91YmxlKShmbl9hZGQtYWRkMCkpOwoKCWZjbG9zZShtYXApOwoJZnJlZShidWYpOwoKCXJldHVybiBFWElUX1NVQ0NFU1M7Cn0K