LyohIFxmaWxlIGJ0R2VuZXJpY1Bvb2xBbGxvY2F0b3IuY3BwClxhdXRob3IgRnJhbmNpc2NvIExlf24gTt9qZXJhLiBlbWFpbCBwcm9qZWN0aWxlbWFuQHlhaG9vLmNvbQoKR2VuZXJhbCBwdXJwb3NlIGFsbG9jYXRvciBjbGFzcwoqLwovKgpCdWxsZXQgQ29udGludW91cyBDb2xsaXNpb24gRGV0ZWN0aW9uIGFuZCBQaHlzaWNzIExpYnJhcnkKQ29weXJpZ2h0IChjKSAyMDAzLTIwMDYgRXJ3aW4gQ291bWFucyAgaHR0cDovL2NvbnRpbnVvdXNwaHlzaWNzLmNvbS9CdWxsZXQvCgpUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkICdhcy1pcycsIHdpdGhvdXQgYW55IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4KSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXMgYXJpc2luZyBmcm9tIHRoZSB1c2Ugb2YgdGhpcyBzb2Z0d2FyZS4KUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsCmluY2x1ZGluZyBjb21tZXJjaWFsIGFwcGxpY2F0aW9ucywgYW5kIHRvIGFsdGVyIGl0IGFuZCByZWRpc3RyaWJ1dGUgaXQgZnJlZWx5LApzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgcmVzdHJpY3Rpb25zOgoKMS4gVGhlIG9yaWdpbiBvZiB0aGlzIHNvZnR3YXJlIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkOyB5b3UgbXVzdCBub3QgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmUgaW4gYSBwcm9kdWN0LCBhbiBhY2tub3dsZWRnbWVudCBpbiB0aGUgcHJvZHVjdCBkb2N1bWVudGF0aW9uIHdvdWxkIGJlIGFwcHJlY2lhdGVkIGJ1dCBpcyBub3QgcmVxdWlyZWQuCjIuIEFsdGVyZWQgc291cmNlIHZlcnNpb25zIG11c3QgYmUgcGxhaW5seSBtYXJrZWQgYXMgc3VjaCwgYW5kIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkIGFzIGJlaW5nIHRoZSBvcmlnaW5hbCBzb2Z0d2FyZS4KMy4gVGhpcyBub3RpY2UgbWF5IG5vdCBiZSByZW1vdmVkIG9yIGFsdGVyZWQgZnJvbSBhbnkgc291cmNlIGRpc3RyaWJ1dGlvbi4KKi8KCiNpbmNsdWRlICJCdWxsZXRDb2xsaXNpb24vR2ltcGFjdC9idEdlbmVyaWNQb29sQWxsb2NhdG9yLmgiCgoKCi8vLyAqKioqKioqKioqKioqKiogYnRHZW5lcmljTWVtb3J5UG9vbCAqKioqKioqKioqKioqKioqKiovLy8vLy8vLy8vLwoKc2l6ZV90IGJ0R2VuZXJpY01lbW9yeVBvb2w6OmFsbG9jYXRlX2Zyb21fZnJlZV9ub2RlcyhzaXplX3QgbnVtX2VsZW1lbnRzKQp7CglzaXplX3QgcHRyID0gQlRfVUlOVF9NQVg7CgoJaWYobV9mcmVlX25vZGVzX2NvdW50ID09IDApIHJldHVybiBCVF9VSU5UX01BWDsKCS8vIGZpbmQgYW4gYXZhbGlhYmxlIGZyZWUgbm9kZSB3aXRoIHRoZSBjb3JyZWN0IHNpemUKCXNpemVfdCByZXZpbmRleCA9IG1fZnJlZV9ub2Rlc19jb3VudDsKCgl3aGlsZShyZXZpbmRleC0tICYmIHB0ciA9PSBCVF9VSU5UX01BWCkKCXsKCQlpZihtX2FsbG9jYXRlZF9zaXplc1ttX2ZyZWVfbm9kZXNbcmV2aW5kZXhdXT49bnVtX2VsZW1lbnRzKQoJCXsKCQkJcHRyID0gcmV2aW5kZXg7CgkJfQoJfQoJaWYocHRyID09IEJUX1VJTlRfTUFYKSByZXR1cm4gQlRfVUlOVF9NQVg7IC8vIG5vdCBmb3VuZAoKCglyZXZpbmRleCA9IHB0cjsKCXB0ciA9IG1fZnJlZV9ub2Rlc1tyZXZpbmRleF07CgkvLyBwb3N0OiBwdHIgY29udGFpbnMgdGhlIG5vZGUgaW5kZXgsIGFuZCByZXZpbmRleCB0aGUgaW5kZXggaW4gbV9mcmVlX25vZGVzCgoJc2l6ZV90ICBmaW5hbHNpemUgPSBtX2FsbG9jYXRlZF9zaXplc1twdHJdOwoJZmluYWxzaXplIC09IG51bV9lbGVtZW50czsKCgltX2FsbG9jYXRlZF9zaXplc1twdHJdID0gbnVtX2VsZW1lbnRzOwoKCS8vIHBvc3Q6IGZpbmFsc2l6ZT49MCwgbV9hbGxvY2F0ZWRfc2l6ZXNbcHRyXSBoYXMgdGhlIHJlcXVlc3RlZCBzaXplCgoJaWYoZmluYWxzaXplPjApIC8vIHByZXNlcnZlIGZyZWUgbm9kZSwgdGhlcmUgYXJlIHNvbWUgZnJlZSBtZW1vcnkKCXsKCQltX2ZyZWVfbm9kZXNbcmV2aW5kZXhdID0gcHRyICsgbnVtX2VsZW1lbnRzOwoJCW1fYWxsb2NhdGVkX3NpemVzW3B0ciArIG51bV9lbGVtZW50c10gPSBmaW5hbHNpemU7Cgl9CgllbHNlIC8vIGRlbGV0ZSBmcmVlIG5vZGUKCXsKCQkvLyBzd2FwIHdpdGggZW5kCgkJbV9mcmVlX25vZGVzW3JldmluZGV4XSA9IG1fZnJlZV9ub2Rlc1ttX2ZyZWVfbm9kZXNfY291bnQtMV07CgkJbV9mcmVlX25vZGVzX2NvdW50LS07Cgl9CgoJcmV0dXJuIHB0cjsKfQoKc2l6ZV90IGJ0R2VuZXJpY01lbW9yeVBvb2w6OmFsbG9jYXRlX2Zyb21fcG9vbChzaXplX3QgbnVtX2VsZW1lbnRzKQp7CglpZihtX2FsbG9jYXRlZF9jb3VudCtudW1fZWxlbWVudHM+bV9tYXhfZWxlbWVudF9jb3VudCkgcmV0dXJuIEJUX1VJTlRfTUFYOwoKCXNpemVfdCBwdHIgPSBtX2FsbG9jYXRlZF9jb3VudDsKCgltX2FsbG9jYXRlZF9zaXplc1ttX2FsbG9jYXRlZF9jb3VudF0gPSBudW1fZWxlbWVudHM7CgltX2FsbG9jYXRlZF9jb3VudCs9bnVtX2VsZW1lbnRzOwoKCXJldHVybiBwdHI7Cn0KCgp2b2lkIGJ0R2VuZXJpY01lbW9yeVBvb2w6OmluaXRfcG9vbChzaXplX3QgZWxlbWVudF9zaXplLCBzaXplX3QgZWxlbWVudF9jb3VudCkKewoJbV9hbGxvY2F0ZWRfY291bnQgPSAwOwoJbV9mcmVlX25vZGVzX2NvdW50ID0gMDsKCgltX2VsZW1lbnRfc2l6ZSA9IGVsZW1lbnRfc2l6ZTsKCW1fbWF4X2VsZW1lbnRfY291bnQgPSBlbGVtZW50X2NvdW50OwoKCgoKCW1fcG9vbCA9ICh1bnNpZ25lZCBjaGFyICopIGJ0QWxpZ25lZEFsbG9jKG1fZWxlbWVudF9zaXplKm1fbWF4X2VsZW1lbnRfY291bnQsMTYpOwoJbV9mcmVlX25vZGVzID0gKHNpemVfdCAqKSBidEFsaWduZWRBbGxvYyhzaXplb2Yoc2l6ZV90KSptX21heF9lbGVtZW50X2NvdW50LDE2KTsKCW1fYWxsb2NhdGVkX3NpemVzID0gKHNpemVfdCAqKSBidEFsaWduZWRBbGxvYyhzaXplb2Yoc2l6ZV90KSptX21heF9lbGVtZW50X2NvdW50LDE2KTsKCglmb3IgKHNpemVfdCBpID0gMDtpPCBtX21heF9lbGVtZW50X2NvdW50O2krKyApCgl7CgkJbV9hbGxvY2F0ZWRfc2l6ZXNbaV0gPSAwOwoJfQp9Cgp2b2lkIGJ0R2VuZXJpY01lbW9yeVBvb2w6OmVuZF9wb29sKCkKewoJYnRBbGlnbmVkRnJlZShtX3Bvb2wpOwoJYnRBbGlnbmVkRnJlZShtX2ZyZWVfbm9kZXMpOwoJYnRBbGlnbmVkRnJlZShtX2FsbG9jYXRlZF9zaXplcyk7CgltX2FsbG9jYXRlZF9jb3VudCA9IDA7CgltX2ZyZWVfbm9kZXNfY291bnQgPSAwOwp9CgoKLy8hIEFsbG9jYXRlcyBtZW1vcnkgaW4gcG9vbAovKiEKXHBhcmFtIHNpemVfYnl0ZXMgc2l6ZSBpbiBieXRlcyBvZiB0aGUgYnVmZmVyCiovCnZvaWQgKiBidEdlbmVyaWNNZW1vcnlQb29sOjphbGxvY2F0ZShzaXplX3Qgc2l6ZV9ieXRlcykKewoKCXNpemVfdCBtb2R1bGUgPSBzaXplX2J5dGVzJW1fZWxlbWVudF9zaXplOwoJc2l6ZV90IGVsZW1lbnRfY291bnQgPSBzaXplX2J5dGVzL21fZWxlbWVudF9zaXplOwoJaWYobW9kdWxlPjApIGVsZW1lbnRfY291bnQrKzsKCglzaXplX3QgYWxsb2NfcG9zID0gYWxsb2NhdGVfZnJvbV9mcmVlX25vZGVzKGVsZW1lbnRfY291bnQpOwoJLy8gYSBmcmVlIG5vZGUgaXMgZm91bmQKCWlmKGFsbG9jX3BvcyAhPSBCVF9VSU5UX01BWCkKCXsKCQlyZXR1cm4gZ2V0X2VsZW1lbnRfZGF0YShhbGxvY19wb3MpOwoJfQoJLy8gYWxsb2NhdGUgZGlyZWN0bHkgb24gcG9vbAoJYWxsb2NfcG9zID0gYWxsb2NhdGVfZnJvbV9wb29sKGVsZW1lbnRfY291bnQpOwoKCWlmKGFsbG9jX3BvcyA9PSBCVF9VSU5UX01BWCkgcmV0dXJuIE5VTEw7IC8vIG5vdCBzcGFjZQoJcmV0dXJuIGdldF9lbGVtZW50X2RhdGEoYWxsb2NfcG9zKTsKfQoKYm9vbCBidEdlbmVyaWNNZW1vcnlQb29sOjpmcmVlTWVtb3J5KHZvaWQgKiBwb2ludGVyKQp7Cgl1bnNpZ25lZCBjaGFyICogcG9pbnRlcl9wb3MgPSAodW5zaWduZWQgY2hhciAqKXBvaW50ZXI7Cgl1bnNpZ25lZCBjaGFyICogcG9vbF9wb3MgPSAodW5zaWduZWQgY2hhciAqKW1fcG9vbDsKCS8vIGNhbGMgb2Zmc2V0CglpZihwb2ludGVyX3Bvczxwb29sX3BvcykgcmV0dXJuIGZhbHNlOy8vb3RoZXIgcG9vbAoJc2l6ZV90IG9mZnNldCA9IHNpemVfdChwb2ludGVyX3BvcyAtIHBvb2xfcG9zKTsKCWlmKG9mZnNldD49Z2V0X3Bvb2xfY2FwYWNpdHkoKSkgcmV0dXJuIGZhbHNlOy8vIGZhciBhd2F5CgoJLy8gZmluZCBmcmVlIHBvc2l0aW9uCgltX2ZyZWVfbm9kZXNbbV9mcmVlX25vZGVzX2NvdW50XSA9IG9mZnNldC9tX2VsZW1lbnRfc2l6ZTsKCW1fZnJlZV9ub2Rlc19jb3VudCsrOwoJcmV0dXJuIHRydWU7Cn0KCgovLy8gKioqKioqKioqKioqKioqKioqKiEgYnRHZW5lcmljUG9vbEFsbG9jYXRvciAqKioqKioqKioqKioqKioqKioqIS8vLwoKCmJ0R2VuZXJpY1Bvb2xBbGxvY2F0b3I6On5idEdlbmVyaWNQb29sQWxsb2NhdG9yKCkKewoJLy8gZGVzdHJveSBwb29scwoJc2l6ZV90IGk7Cglmb3IgKGk9MDtpPG1fcG9vbF9jb3VudDtpKyspCgl7CgkJbV9wb29sc1tpXS0+ZW5kX3Bvb2woKTsKCQlidEFsaWduZWRGcmVlKG1fcG9vbHNbaV0pOwoJfQp9CgoKLy8gY3JlYXRlcyBhIHBvb2wKYnRHZW5lcmljTWVtb3J5UG9vbCAqIGJ0R2VuZXJpY1Bvb2xBbGxvY2F0b3I6OnB1c2hfbmV3X3Bvb2woKQp7CglpZihtX3Bvb2xfY291bnQgPj0gQlRfREVGQVVMVF9NQVhfUE9PTFMpIHJldHVybiBOVUxMOwoKCWJ0R2VuZXJpY01lbW9yeVBvb2wgKiBuZXdwdHIgPSAoYnRHZW5lcmljTWVtb3J5UG9vbCAqKWJ0QWxpZ25lZEFsbG9jKHNpemVvZihidEdlbmVyaWNNZW1vcnlQb29sKSwxNik7CgoJbV9wb29sc1ttX3Bvb2xfY291bnRdID0gbmV3cHRyOwoKCW1fcG9vbHNbbV9wb29sX2NvdW50XS0+aW5pdF9wb29sKG1fcG9vbF9lbGVtZW50X3NpemUsbV9wb29sX2VsZW1lbnRfY291bnQpOwoKCW1fcG9vbF9jb3VudCsrOwoJcmV0dXJuIG5ld3B0cjsKfQoKdm9pZCAqIGJ0R2VuZXJpY1Bvb2xBbGxvY2F0b3I6OmZhaWxiYWNrX2FsbG9jKHNpemVfdCBzaXplX2J5dGVzKQp7CgoJYnRHZW5lcmljTWVtb3J5UG9vbCAqIHBvb2wgPSBOVUxMOwoKCglpZihzaXplX2J5dGVzPD1nZXRfcG9vbF9jYXBhY2l0eSgpKQoJewoJCXBvb2wgPSAJcHVzaF9uZXdfcG9vbCgpOwoJfQoKCWlmKHBvb2w9PU5VTEwpIC8vIGZhaWxiYWNrCgl7CgkJcmV0dXJuIGJ0QWxpZ25lZEFsbG9jKHNpemVfYnl0ZXMsMTYpOwoJfQoKCXJldHVybiBwb29sLT5hbGxvY2F0ZShzaXplX2J5dGVzKTsKfQoKYm9vbCBidEdlbmVyaWNQb29sQWxsb2NhdG9yOjpmYWlsYmFja19mcmVlKHZvaWQgKiBwb2ludGVyKQp7CglidEFsaWduZWRGcmVlKHBvaW50ZXIpOwoJcmV0dXJuIHRydWU7Cn0KCgovLyEgQWxsb2NhdGVzIG1lbW9yeSBpbiBwb29sCi8qIQpccGFyYW0gc2l6ZV9ieXRlcyBzaXplIGluIGJ5dGVzIG9mIHRoZSBidWZmZXIKKi8Kdm9pZCAqIGJ0R2VuZXJpY1Bvb2xBbGxvY2F0b3I6OmFsbG9jYXRlKHNpemVfdCBzaXplX2J5dGVzKQp7Cgl2b2lkICogcHRyID0gTlVMTDsKCglzaXplX3QgaSA9IDA7Cgl3aGlsZShpPG1fcG9vbF9jb3VudCAmJiBwdHIgPT0gTlVMTCkKCXsKCQlwdHIgPSBtX3Bvb2xzW2ldLT5hbGxvY2F0ZShzaXplX2J5dGVzKTsKCQkrK2k7Cgl9CgoJaWYocHRyKSByZXR1cm4gcHRyOwoKCXJldHVybiBmYWlsYmFja19hbGxvYyhzaXplX2J5dGVzKTsKfQoKYm9vbCBidEdlbmVyaWNQb29sQWxsb2NhdG9yOjpmcmVlTWVtb3J5KHZvaWQgKiBwb2ludGVyKQp7Cglib29sIHJlc3VsdCA9IGZhbHNlOwoKCXNpemVfdCBpID0gMDsKCXdoaWxlKGk8bV9wb29sX2NvdW50ICYmIHJlc3VsdCA9PSBmYWxzZSkKCXsKCQlyZXN1bHQgPSBtX3Bvb2xzW2ldLT5mcmVlTWVtb3J5KHBvaW50ZXIpOwoJCSsraTsKCX0KCglpZihyZXN1bHQpIHJldHVybiB0cnVlOwoKCXJldHVybiBmYWlsYmFja19mcmVlKHBvaW50ZXIpOwp9CgovLy8gKioqKioqKioqKioqKiogU1RBTkRBUkQgQUxMT0NBVE9SICoqKioqKioqKioqKioqKioqKioqKioqKioqKi8vLwoKCiNkZWZpbmUgQlRfREVGQVVMVF9QT09MX1NJWkUgMzI3NjgKI2RlZmluZSBCVF9ERUZBVUxUX1BPT0xfRUxFTUVOVF9TSVpFIDgKCi8vIG1haW4gYWxsb2NhdG9yCmNsYXNzIEdJTV9TVEFOREFSRF9BTExPQ0FUT1I6IHB1YmxpYyBidEdlbmVyaWNQb29sQWxsb2NhdG9yCnsKcHVibGljOgoJR0lNX1NUQU5EQVJEX0FMTE9DQVRPUigpOmJ0R2VuZXJpY1Bvb2xBbGxvY2F0b3IoQlRfREVGQVVMVF9QT09MX0VMRU1FTlRfU0laRSxCVF9ERUZBVUxUX1BPT0xfU0laRSkKCXsKCX0KfTsKCi8vIGdsb2JhbCBhbGxvY2F0b3IKR0lNX1NUQU5EQVJEX0FMTE9DQVRPUiBnX21haW5fYWxsb2NhdG9yOwoKCnZvaWQgKiBidFBvb2xBbGxvYyhzaXplX3Qgc2l6ZSkKewoJcmV0dXJuIGdfbWFpbl9hbGxvY2F0b3IuYWxsb2NhdGUoc2l6ZSk7Cn0KCnZvaWQgKiBidFBvb2xSZWFsbG9jKHZvaWQgKnB0ciwgc2l6ZV90IG9sZHNpemUsIHNpemVfdCBuZXdzaXplKQp7Cgl2b2lkICogbmV3cHRyID0gYnRQb29sQWxsb2MobmV3c2l6ZSk7CiAgICBzaXplX3QgY29weXNpemUgPSBvbGRzaXplPG5ld3NpemU/b2xkc2l6ZTpuZXdzaXplOwogICAgbWVtY3B5KG5ld3B0cixwdHIsY29weXNpemUpOwogICAgYnRQb29sRnJlZShwdHIpOwogICAgcmV0dXJuIG5ld3B0cjsKfQoKdm9pZCBidFBvb2xGcmVlKHZvaWQgKnB0cikKewoJZ19tYWluX2FsbG9jYXRvci5mcmVlTWVtb3J5KHB0cik7Cn0K