LyoKICogRElTUERJQi5kbGwKICoKICogQ29weXJpZ2h0IDE5OTggT3ZlIEvldmVuICh3aXRoIHNvbWUgaGVscCBmcm9tIE1hcmN1cyBNZWlzc25lcikKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiAqLwoKI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSAid2luZGVmLmgiCiNpbmNsdWRlICJ3aW5nZGkuaCIKI2luY2x1ZGUgIndpbmUvd2luZ2RpMTYuaCIKI2luY2x1ZGUgImRpc3BkaWIuaCIKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKGRkcmF3KTsKCiNpZiAwCgpzdGF0aWMgaW50IGRpc3BkaWJfbXVsdGkgPSAwOwoKc3RhdGljIFdPUkQgRElTUERJQl9CZWdpbihXT1JEIHdGbGFncykKewogICAgdW5zaWduZWQgWHJlcyxZcmVzLERlcHRoOwoKICAgIHN3aXRjaCh3RmxhZ3MmRElTUExBWURJQl9NT0RFKSB7CiAgICAgICAgY2FzZSBESVNQTEFZRElCX01PREVfREVGQVVMVDoKICAgICAgICAgICAgLyogRklYTUU6IGlzIHRoaXMgc3VwcG9zZWQgdG8gYXV0b2RldGVjdD8gKi8KICAgICAgICBjYXNlIERJU1BMQVlESUJfTU9ERV8zMjB4MjAweDg6CiAgICAgICAgICAgIFhyZXM9MzIwOyBZcmVzPTIwMDsgRGVwdGg9ODsgYnJlYWs7CiAgICAgICAgY2FzZSBESVNQTEFZRElCX01PREVfMzIweDI0MHg4OgogICAgICAgICAgICBYcmVzPTMyMDsgWXJlcz0yNDA7IERlcHRoPTg7IGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHJldHVybiBESVNQTEFZRElCX05PVFNVUFBPUlRFRDsKICAgIH0KICAgIC8qIG1vcmUgb3IgbGVzcyBkdW1teSBjYWxscyB0byBEZWF0aC9SZXN1cnJlY3Rpb24sIGZvciBjb21wbGV0ZW5lc3MgKi8KICAgIC8qIEZJWE1FOiB3aGF0IGFyZ3VtZW50cyBzaG91bGQgdGhleSBnZXQ/ICovCiAgICBEZWF0aDE2KDApOwogICAgaWYgKFZHQV9TZXRNb2RlKFhyZXMsWXJlcyxEZXB0aCkpIHsKICAgICAgICAgUmVzdXJyZWN0aW9uMTYoMCwwLDAsMCwwLDAsMCk7CiAgICAgICAgIHJldHVybiBESVNQTEFZRElCX05PVFNVUFBPUlRFRDsKICAgIH0KICAgIHJldHVybiBESVNQTEFZRElCX05PRVJST1I7Cn0KCnN0YXRpYyB2b2lkIERJU1BESUJfRW5kKHZvaWQpCnsKICAgIFJlc3VycmVjdGlvbjE2KDAsMCwwLDAsMCwwLDApOyAvKiBGSVhNRTogYXJndW1lbnRzICovCiAgICBWR0FfRXhpdCgpOwp9CgpzdGF0aWMgdm9pZCBESVNQRElCX1BhbGV0dGUoTFBCSVRNQVBJTkZPIGxwYmkpCnsKICAgIFZHQV9TZXRRdWFkUGFsZXR0ZShscGJpLT5ibWlDb2xvcnMsMCwyNTYpOwp9CgpzdGF0aWMgdm9pZCBESVNQRElCX1Nob3coTFBCSVRNQVBJTkZPSEVBREVSIGxwYmksTFBTVFIgbHBCaXRzLFdPUkQgdUZsYWdzKQp7CiAgICBpbnQgWG9mcyxZb2ZzLFdpZHRoPWxwYmktPmJpV2lkdGgsSGVpZ2h0PWxwYmktPmJpSGVpZ2h0LERlbHRhOwogICAgaW50IFBpdGNoID0gKFdpZHRoICsgMykgJiB+MzsKICAgIHVuc2lnbmVkIGludCBzUGl0Y2gsc1dpZHRoLHNIZWlnaHQ7CiAgICBMUFNUUiBzdXJmID0gRE9TTUVNX01hcERvc1RvTGluZWFyKDB4YTAwMDApOwoKICAgIGlmIChWR0FfR2V0TW9kZSgmc0hlaWdodCwmc1dpZHRoLE5VTEwpKSByZXR1cm47CiAgICBzUGl0Y2g9MzIwOwoKICAgIERlbHRhPShIZWlnaHQ8MCkqMi0xOwogICAgSGVpZ2h0Kj0tRGVsdGE7IFBpdGNoKj1EZWx0YTsKCiAgICBpZiAodUZsYWdzJkRJU1BMQVlESUJfTk9DRU5URVIpIHsKICAgICAgICBYb2ZzPTA7IFlvZnM9MDsKICAgIH0gZWxzZSB7CiAgICAgICAgWG9mcz0oc1dpZHRoLVdpZHRoKS8yOwogICAgICAgIFlvZnM9KHNIZWlnaHQtSGVpZ2h0KS8yOwogICAgfQogICAgc3VyZiArPSAoWW9mcypzUGl0Y2gpK1hvZnM7CiAgICBpZiAoUGl0Y2g8MCkgbHBCaXRzLT1QaXRjaCooSGVpZ2h0LTEpOwogICAgZm9yICg7IEhlaWdodDsgSGVpZ2h0LS0sbHBCaXRzKz1QaXRjaCxzdXJmKz1zUGl0Y2gpIHsKICAgICAgICBtZW1jcHkoc3VyZixscEJpdHMsV2lkdGgpOwogICAgfQoKICAgIFZHQV9Qb2xsKDApOwp9CiNlbmRpZgoKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICoJRGlzcGxheURpYgkoRElTUERJQi4xKQogKgogKiAgRGlzYWJsZXMgR0RJIGFuZCB0YWtlcyBvdmVyIHRoZSBWR0Egc2NyZWVuIHRvIHNob3cgRElCcyBpbiBmdWxsIHNjcmVlbi4KICoKICogRkxBR1MKICoKICogIERJU1BMQVlESUJfTk9QQUxFVFRFOiBkb24ndCBjaGFuZ2UgcGFsZXR0ZQogKiAgRElTUExBWURJQl9OT0NFTlRFUjogZG9uJ3QgY2VudGVyIGJpdG1hcAogKiAgRElTUExBWURJQl9OT1dBSVQ6IGRvbid0IHdhaXQgKGZvciBrZXlwcmVzcykgYmVmb3JlIHJldHVybmluZwogKiAgRElTUExBWURJQl9CRUdJTjogc3RhcnQgb2YgbXVsdGlwbGUgY2FsbHMgKGRvZXMgbm90IHJlc3RvcmUgdGhlIHNjcmVlbikKICogIERJU1BMQVlESUJfRU5EOiBlbmQgb2YgbXVsdGlwbGUgY2FsbHMgKHJlc3RvcmVzIHRoZSBzY3JlZW4pCiAqICBESVNQTEFZRElCX01PREVfREVGQVVMVDogZGVmYXVsdCBkaXNwbGF5IG1vZGUKICogIERJU1BMQVlESUJfTU9ERV8zMjB4MjAweDg6IFN0YW5kYXJkIFZHQSAzMjB4MjAwIDI1NiBjb2xvcnMKICogIERJU1BMQVlESUJfTU9ERV8zMjB4MjQweDg6IFR3ZWFrZWQgVkdBIDMyMHgyNDAgMjU2IGNvbG9ycwogKgogKiBSRVRVUk5TCiAqCiAqICBESVNQTEFZRElCX05PRVJST1I6IHN1Y2Nlc3MKICogIERJU1BMQVlESUJfTk9UU1VQUE9SVEVEOiBmdW5jdGlvbiBub3Qgc3VwcG9ydGVkCiAqICBESVNQTEFZRElCX0lOVkFMSURESUI6IG51bGwgb3IgaW52YWxpZCBESUIgaGVhZGVyCiAqICBESVNQTEFZRElCX0lOVkFMSURGT1JNQVQ6IGludmFsaWQgRElCIGZvcm1hdAogKiAgRElTUExBWURJQl9JTlZBTElEVEFTSzogbm90IGNhbGxlZCBmcm9tIGN1cnJlbnQgdGFzawogKgogKiBCVUdTCiAqCiAqICBXYWl0aW5nIGZvciBrZXlwcmVzc2VzIGlzIG5vdCBpbXBsZW1lbnRlZC4KICovCldPUkQgV0lOQVBJIERpc3BsYXlEaWIoCgkJTFBCSVRNQVBJTkZPIGxwYmksIC8qIFtpbl0gRElCIGhlYWRlciB3aXRoIHJlc29sdXRpb24gYW5kIHBhbGV0dGUgKi8KCQlMUFNUUiBscEJpdHMsICAgICAgLyogW2luXSBCaXRtYXAgYml0cyB0byBzaG93ICovCgkJV09SRCB3RmxhZ3MgICAgICAgIC8qIFtpbl0gKi8KCSkKewojaWYgMAogICAgV09SRCByZXQ7CgogICAgaWYgKHdGbGFncyZESVNQTEFZRElCX0VORCkgewogICAgICAgIGlmIChkaXNwZGliX211bHRpKSBESVNQRElCX0VuZCgpOwogICAgICAgIGRpc3BkaWJfbXVsdGkgPSAwOwogICAgICAgIHJldHVybiBESVNQTEFZRElCX05PRVJST1I7CiAgICB9CiAgICBpZiAoIWRpc3BkaWJfbXVsdGkpIHsKICAgICAgICByZXQ9RElTUERJQl9CZWdpbih3RmxhZ3MpOwogICAgICAgIGlmIChyZXQpIHJldHVybiByZXQ7CiAgICB9CiAgICBpZiAod0ZsYWdzJkRJU1BMQVlESUJfQkVHSU4pIGRpc3BkaWJfbXVsdGkgPSAxOwogICAgaWYgKCEod0ZsYWdzJkRJU1BMQVlESUJfTk9QQUxFVFRFKSkgewogICAgICAgIERJU1BESUJfUGFsZXR0ZShscGJpKTsKICAgIH0KICAgIC8qIEZJWE1FOiBub3Qgc3VyZSBpZiBpdCdzIHZhbGlkIHRvIGRyYXcgaW1hZ2VzIGluIERJU1BMQVlESUJfQkVHSU4sIHNvLi4uICovCiAgICBpZiAobHBCaXRzKSB7CiAgICAgICAgRElTUERJQl9TaG93KCYobHBiaS0+Ym1pSGVhZGVyKSxscEJpdHMsd0ZsYWdzKTsKICAgIH0KICAgIGlmICghKHdGbGFncyZESVNQTEFZRElCX05PV0FJVCkpIHsKICAgICAgICBGSVhNRSgid2FpdCBub3QgaW1wbGVtZW50ZWRcbiIpOwogICAgfQogICAgaWYgKCFkaXNwZGliX211bHRpKSBESVNQRElCX0VuZCgpOwojZW5kaWYKICAgIEZJWE1FKCAiYnJva2VuLCBzaG91bGQgYmUgcmV3cml0dGVuIHVzaW5nIGRkcmF3XG4iICk7CiAgICByZXR1cm4gRElTUExBWURJQl9OT0VSUk9SOwp9Cg==