Ly8gQ29weXJpZ2h0IEdvdHRmcmllZCBHYW7fYXVnZSAyMDAzLi4yMDA2LgovLyBEaXN0cmlidXRlZCB1bmRlciB0aGUgQm9vc3QgU29mdHdhcmUgTGljZW5zZSwgVmVyc2lvbiAxLjAuIChTZWUKLy8gYWNjb21wYW55aW5nIGZpbGUgTElDRU5TRV8xXzAudHh0IG9yIGNvcHkgYXQKLy8gaHR0cDovL3d3dy5ib29zdC5vcmcvTElDRU5TRV8xXzAudHh0KQovKgogKiBHZW5lcmljIENvbnZlcnNpb24gb2Ygb3BhcXVlIEMrKy1wb2ludGVycyB0byBhIFB5dGhvbi1XcmFwcGVyLgogKi8KIyBpZm5kZWYgT1BBUVVFX1BPSU5URVJfQ09OVkVSVEVSX0hQUF8KIyBkZWZpbmUgT1BBUVVFX1BPSU5URVJfQ09OVkVSVEVSX0hQUF8KCiMgaW5jbHVkZSA8Ym9vc3QvcHl0aG9uL2RldGFpbC9wcmVmaXguaHBwPgojIGluY2x1ZGUgPGJvb3N0L3B5dGhvbi9sdmFsdWVfZnJvbV9weXR5cGUuaHBwPgojIGluY2x1ZGUgPGJvb3N0L3B5dGhvbi90b19weXRob25fY29udmVydGVyLmhwcD4KIyBpbmNsdWRlIDxib29zdC9weXRob24vY29udmVydGVyL3JlZ2lzdHJhdGlvbnMuaHBwPgojIGluY2x1ZGUgPGJvb3N0L3B5dGhvbi9kZXRhaWwvZGVhbGxvYy5ocHA+CiMgaW5jbHVkZSA8Ym9vc3QvcHl0aG9uL2RldGFpbC9ub25lLmhwcD4KIyBpbmNsdWRlIDxib29zdC9weXRob24vdHlwZV9pZC5ocHA+CiMgaW5jbHVkZSA8Ym9vc3QvcHl0aG9uL2Vycm9ycy5ocHA+CgojIGluY2x1ZGUgPGJvb3N0L3R5cGVfdHJhaXRzL3JlbW92ZV9wb2ludGVyLmhwcD4KIyBpbmNsdWRlIDxib29zdC90eXBlX3RyYWl0cy9pc19wb2ludGVyLmhwcD4KIyBpbmNsdWRlIDxib29zdC90eXBlX3RyYWl0cy9pc192b2lkLmhwcD4KCiMgaW5jbHVkZSA8Ym9vc3QvaW1wbGljaXRfY2FzdC5ocHA+CgojIGluY2x1ZGUgPGJvb3N0L21wbC9ldmFsX2lmLmhwcD4KIyBpbmNsdWRlIDxib29zdC9tcGwvaWRlbnRpdHkuaHBwPgojIGluY2x1ZGUgPGJvb3N0L21wbC9hc3NlcnQuaHBwPgoKLy8gb3BhcXVlIC0tCi8vCi8vIHJlZ2lzdGVycyB0by0gYW5kIGZyb20tIHB5dGhvbiBjb252ZXJzaW9ucyBmb3IgYSB0eXBlIFBvaW50ZWUuCi8vCi8vIE5vdGU6Ci8vIEluIGFkZGl0aW9uIHlvdSBuZWVkIHRvIGRlZmluZSBzcGVjaWFsaXphdGlvbnMgZm9yIHR5cGVfaWQKLy8gb24gdGhlIHR5cGUgcG9pbnRlZCB0byBieSBQb2ludGVyIHVzaW5nCi8vIEJPT1NUX1BZVEhPTl9PUEFRVUVfU1BFQ0lBTElaRURfVFlQRV9JRChQb2ludGVlKQovLwovLyBGb3IgYW4gZXhhbXBsZSBzZWUgbGlicy9weXRob24vdGVzdC9vcGFxdWUuY3BwCi8vCm5hbWVzcGFjZSBib29zdCB7IG5hbWVzcGFjZSBweXRob24gewoKdGVtcGxhdGUgPGNsYXNzIFBvaW50ZWU+CnN0cnVjdCBvcGFxdWUKewogICAgb3BhcXVlKCkKICAgIHsKICAgICAgICBpZiAodHlwZV9vYmplY3QudHBfbmFtZSA9PSAwKQogICAgICAgIHsKICAgICAgICAgICAgdHlwZV9vYmplY3QudHBfbmFtZSA9IGNvbnN0X2Nhc3Q8Y2hhcio+KHR5cGVfaWQ8UG9pbnRlZSo+KCkubmFtZSgpKTsKICAgICAgICAgICAgaWYgKFB5VHlwZV9SZWFkeSAoJnR5cGVfb2JqZWN0KSA8IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRocm93IGVycm9yX2FscmVhZHlfc2V0KCk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHRoaXMtPnJlZ2lzdGVyX3NlbGYoKTsKICAgICAgICB9CiAgICB9CiAgICAKICAgIHN0YXRpYyBvcGFxdWUgaW5zdGFuY2U7CnByaXZhdGU6CiAgICAKICAgIHN0YXRpYyB2b2lkKiBleHRyYWN0KFB5T2JqZWN0KiBvcCkKICAgIHsKICAgICAgICByZXR1cm4gUHlPYmplY3RfVHlwZUNoZWNrKG9wLCAmdHlwZV9vYmplY3QpCiAgICAgICAgICAgID8gc3RhdGljX2Nhc3Q8cHl0aG9uX2luc3RhbmNlKj4oaW1wbGljaXRfY2FzdDx2b2lkKj4ob3ApKS0+eAogICAgICAgICAgICA6IDAKICAgICAgICAgICAgOwogICAgfQoKICAgIHN0YXRpYyBQeU9iamVjdCogd3JhcCh2b2lkIGNvbnN0KiBweCkKICAgIHsKICAgICAgICBQb2ludGVlKiB4ID0gKnN0YXRpY19jYXN0PFBvaW50ZWUqY29uc3QqPihweCk7CiAgICAgICAgCiAgICAgICAgaWYgKHggPT0gMCkKICAgICAgICAgICAgcmV0dXJuIGRldGFpbDo6bm9uZSgpOwoKICAgICAgICBpZiAoIHB5dGhvbl9pbnN0YW5jZSAqbyA9IFB5T2JqZWN0X05ldyhweXRob25faW5zdGFuY2UsICZ0eXBlX29iamVjdCkgKQogICAgICAgIHsKICAgICAgICAgICAgby0+eCA9IHg7CiAgICAgICAgICAgIHJldHVybiBzdGF0aWNfY2FzdDxQeU9iamVjdCo+KGltcGxpY2l0X2Nhc3Q8dm9pZCo+KG8pKTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgdGhyb3cgZXJyb3JfYWxyZWFkeV9zZXQoKTsKICAgICAgICB9CiAgICB9CgogICAgdm9pZCByZWdpc3Rlcl9zZWxmKCkKICAgIHsKICAgICAgICBjb252ZXJ0ZXI6OnJlZ2lzdHJhdGlvbiBjb25zdCAqZXhpc3RpbmcgPQogICAgICAgICAgICBjb252ZXJ0ZXI6OnJlZ2lzdHJ5OjpxdWVyeSAodHlwZV9pZDxQb2ludGVlKj4oKSk7CgogICAgICAgIGlmICgoZXhpc3RpbmcgPT0gMCkgfHwgKGV4aXN0aW5nLT5tX3RvX3B5dGhvbiA9PSAwKSkKICAgICAgICB7CiNpZm5kZWYgQk9PU1RfUFlUSE9OX05PX1BZX1NJR05BVFVSRVMKICAgICAgICAgICAgY29udmVydGVyOjpyZWdpc3RyeTo6aW5zZXJ0KCZleHRyYWN0LCB0eXBlX2lkPFBvaW50ZWU+KCksICZnZXRfcHl0eXBlKTsKICAgICAgICAgICAgY29udmVydGVyOjpyZWdpc3RyeTo6aW5zZXJ0KCZ3cmFwLCB0eXBlX2lkPFBvaW50ZWUqPigpLCAmZ2V0X3B5dHlwZSk7CiNlbHNlCiAgICAgICAgICAgIGNvbnZlcnRlcjo6cmVnaXN0cnk6Omluc2VydCgmZXh0cmFjdCwgdHlwZV9pZDxQb2ludGVlPigpKTsKICAgICAgICAgICAgY29udmVydGVyOjpyZWdpc3RyeTo6aW5zZXJ0KCZ3cmFwLCB0eXBlX2lkPFBvaW50ZWUqPigpKTsKI2VuZGlmCiAgICAgICAgfQogICAgfQoKICAgIHN0cnVjdCBweXRob25faW5zdGFuY2UKICAgIHsKICAgICAgICBQeU9iamVjdF9IRUFECiAgICAgICAgUG9pbnRlZSogeDsKICAgIH07CiAgICAKICAgIHN0YXRpYyBQeVR5cGVPYmplY3QgdHlwZV9vYmplY3Q7CiNpZm5kZWYgQk9PU1RfUFlUSE9OX05PX1BZX1NJR05BVFVSRVMKICAgIHN0YXRpYyBQeVR5cGVPYmplY3QgY29uc3QgKmdldF9weXR5cGUoKXtyZXR1cm4gICZ0eXBlX29iamVjdDsgfQojZW5kaWYKfTsKCnRlbXBsYXRlIDxjbGFzcyBQb2ludGVlPgpvcGFxdWU8UG9pbnRlZT4gb3BhcXVlPFBvaW50ZWU+OjppbnN0YW5jZTsKCnRlbXBsYXRlIDxjbGFzcyBQb2ludGVlPgpQeVR5cGVPYmplY3Qgb3BhcXVlPFBvaW50ZWU+Ojp0eXBlX29iamVjdCA9CnsKICAgIFB5VmFyT2JqZWN0X0hFQURfSU5JVChOVUxMLCAwKQogICAgMCwKICAgIHNpemVvZiggQk9PU1RfREVEVUNFRF9UWVBFTkFNRSBvcGFxdWU8UG9pbnRlZT46OnB5dGhvbl9pbnN0YW5jZSApLAogICAgMCwKICAgIDo6Ym9vc3Q6OnB5dGhvbjo6ZGV0YWlsOjpkZWFsbG9jLAogICAgMCwgICAgICAgICAgLyogdHBfcHJpbnQgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2dldGF0dHIgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX3NldGF0dHIgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2NvbXBhcmUgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX3JlcHIgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2FzX251bWJlciAqLwogICAgMCwgICAgICAgICAgLyogdHBfYXNfc2VxdWVuY2UgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2FzX21hcHBpbmcgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2hhc2ggKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2NhbGwgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX3N0ciAqLwogICAgMCwgICAgICAgICAgLyogdHBfZ2V0YXR0cm8gKi8KICAgIDAsICAgICAgICAgIC8qIHRwX3NldGF0dHJvICovCiAgICAwLCAgICAgICAgICAvKiB0cF9hc19idWZmZXIgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2ZsYWdzICovCiAgICAwLCAgICAgICAgICAvKiB0cF9kb2MgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX3RyYXZlcnNlICovCiAgICAwLCAgICAgICAgICAvKiB0cF9jbGVhciAqLwogICAgMCwgICAgICAgICAgLyogdHBfcmljaGNvbXBhcmUgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX3dlYWtsaXN0b2Zmc2V0ICovCiAgICAwLCAgICAgICAgICAvKiB0cF9pdGVyICovCiAgICAwLCAgICAgICAgICAvKiB0cF9pdGVybmV4dCAqLwogICAgMCwgICAgICAgICAgLyogdHBfbWV0aG9kcyAqLwogICAgMCwgICAgICAgICAgLyogdHBfbWVtYmVycyAqLwogICAgMCwgICAgICAgICAgLyogdHBfZ2V0c2V0ICovCiAgICAwLCAgICAgICAgICAvKiB0cF9iYXNlICovCiAgICAwLCAgICAgICAgICAvKiB0cF9kaWN0ICovCiAgICAwLCAgICAgICAgICAvKiB0cF9kZXNjcl9nZXQgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2Rlc2NyX3NldCAqLwogICAgMCwgICAgICAgICAgLyogdHBfZGljdG9mZnNldCAqLwogICAgMCwgICAgICAgICAgLyogdHBfaW5pdCAqLwogICAgMCwgICAgICAgICAgLyogdHBfYWxsb2MgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX25ldyAqLwogICAgMCwgICAgICAgICAgLyogdHBfZnJlZSAqLwogICAgMCwgICAgICAgICAgLyogdHBfaXNfZ2MgKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2Jhc2VzICovCiAgICAwLCAgICAgICAgICAvKiB0cF9tcm8gKi8KICAgIDAsICAgICAgICAgIC8qIHRwX2NhY2hlICovCiAgICAwLCAgICAgICAgICAvKiB0cF9zdWJjbGFzc2VzICovCiAgICAwLCAgICAgICAgICAvKiB0cF93ZWFrbGlzdCAqLwojaWYgUFlUSE9OX0FQSV9WRVJTSU9OID49IDEwMTIKICAgIDAgICAgICAgICAgIC8qIHRwX2RlbCAqLwojZW5kaWYKfTsKfX0gLy8gbmFtZXNwYWNlIGJvb3N0OjpweXRob24KCiMgIGlmIEJPT1NUX1dPUktBUk9VTkQoQk9PU1RfTVNWQywgPD0gMTMwMCkKCiMgIGRlZmluZSBCT09TVF9QWVRIT05fT1BBUVVFX1NQRUNJQUxJWkVEX1RZUEVfSUQoUG9pbnRlZSkKCiMgIGVsc2UKCi8vIElmIHlvdSBjaGFuZ2UgdGhlIGJlbG93LCBkb24ndCBmb3JnZXQgdG8gYWx0ZXIgdGhlIGVuZCBvZiB0eXBlX2lkLmhwcAojICAgZGVmaW5lIEJPT1NUX1BZVEhPTl9PUEFRVUVfU1BFQ0lBTElaRURfVFlQRV9JRChQb2ludGVlKSAgICAgICAgICAgICAgICAgICAgIFwKICAgIG5hbWVzcGFjZSBib29zdCB7IG5hbWVzcGFjZSBweXRob24geyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICB0ZW1wbGF0ZTw+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgaW5saW5lIHR5cGVfaW5mbyB0eXBlX2lkPFBvaW50ZWU+KEJPT1NUX1BZVEhPTl9FWFBMSUNJVF9UVF9ERUYoUG9pbnRlZSkpICAgIFwKICAgIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgcmV0dXJuIHR5cGVfaW5mbyAodHlwZWlkIChQb2ludGVlICopKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgIHRlbXBsYXRlPD4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBpbmxpbmUgdHlwZV9pbmZvIHR5cGVfaWQ8Y29uc3Qgdm9sYXRpbGUgUG9pbnRlZSY+KCAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIEJPT1NUX1BZVEhPTl9FWFBMSUNJVF9UVF9ERUYoY29uc3Qgdm9sYXRpbGUgUG9pbnRlZSYpKSAgICAgICAgICAgICAgICAgIFwKICAgIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgcmV0dXJuIHR5cGVfaW5mbyAodHlwZWlkIChQb2ludGVlICopKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgIH19CgojICBlbmRpZgoKIyBlbmRpZiAgICAvLyBPUEFRVUVfUE9JTlRFUl9DT05WRVJURVJfSFBQXwo=