LyoKICogQ2xvY2sKICoKICogQ29weXJpZ2h0IDE5OTggTWFyY2VsIEJhdXIgPG1iYXVyQGcyNi5ldGh6LmNoPgogKiBDb3B5cmlnaHQgMTk5OCBLYXJsIEJhY2tzdHL2bSA8a2FybF9iQGdlb2NpdGllcy5jb20+CiAqCiAqIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIKICogdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVQogKiBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQogKi8KCiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSAid2luZG93cy5oIgojaW5jbHVkZSAibWFpbi5oIgojaW5jbHVkZSAibGFuZ3VhZ2UuaCIKI2luY2x1ZGUgIndpbm5scy5oIgoKQ0hBUiBTVFJJTkdfTUVOVV9YeFtdICAgICAgPSAiTUVOVV9YeCI7CgpWT0lEIExBTkdVQUdFX1VwZGF0ZU1lbnVDaGVja21hcmtzKFZPSUQpIHsKCiAgICBpZihHbG9iYWxzLmJBbmFsb2cgPT0gVFJVRSkgewogICAgCiAgICAgICAgLyogYW5hbG9nIGNsb2NrICovCiAgICAgICAgCiAgICAgICAgQ2hlY2tNZW51SXRlbShHbG9iYWxzLmhQcm9wZXJ0aWVzTWVudSwgQ0xfQU5BTE9HLCBcCiAgICAgICAgICAgICAgICAgICAgICAgTUZfQllDT01NQU5EIHwgTUZfQ0hFQ0tFRCk7CiAgICAgICAgQ2hlY2tNZW51SXRlbShHbG9iYWxzLmhQcm9wZXJ0aWVzTWVudSwgQ0xfRElHSVRBTCwgXAogICAgICAgICAgICAgICAgICAgICAgIE1GX0JZQ09NTUFORCB8IE1GX1VOQ0hFQ0tFRCk7CiAgICAgICAgRW5hYmxlTWVudUl0ZW0oR2xvYmFscy5oUHJvcGVydGllc01lbnUsIENMX0ZPTlQsIFwKICAgICAgICAgICAgICAgICAgICAgICBNRl9CWUNPTU1BTkQgfCBNRl9HUkFZRUQpOwogICAgfQogICAgICAgIGVsc2UgCiAgICB7CiAgICAKICAgICAgICAvKiBkaWdpdGFsIGNsb2NrICovCiAgICAgICAgCiAgICAgICAgQ2hlY2tNZW51SXRlbShHbG9iYWxzLmhQcm9wZXJ0aWVzTWVudSwgQ0xfQU5BTE9HLCBcCiAgICAgICAgICAgICAgICAgICAgICAgTUZfQllDT01NQU5EIHwgTUZfVU5DSEVDS0VEKTsKICAgICAgICBDaGVja01lbnVJdGVtKEdsb2JhbHMuaFByb3BlcnRpZXNNZW51LCBDTF9ESUdJVEFMLCBcCiAgICAgICAgICAgICAgICAgICAgICAgTUZfQllDT01NQU5EIHwgTUZfQ0hFQ0tFRCk7CiAgICAgICAgRW5hYmxlTWVudUl0ZW0oR2xvYmFscy5oUHJvcGVydGllc01lbnUsIENMX0ZPTlQsIFwKICAgICAgICAgICAgICAgICAgICAgICBNRl9CWUNPTU1BTkQpOwogICAgICAgICAgICAgICAgICAgICAgIAogICAgfQogICAgCiAgICBDaGVja01lbnVJdGVtKEdsb2JhbHMuaFByb3BlcnRpZXNNZW51LCBDTF9XSVRIT1VUX1RJVExFLCBNRl9CWUNPTU1BTkQgfCBcCiAgICAgICAgICAgICAgICAgKEdsb2JhbHMuYldpdGhvdXRUaXRsZSA/IE1GX0NIRUNLRUQgOiBNRl9VTkNIRUNLRUQpKTsKICAgIENoZWNrTWVudUl0ZW0oR2xvYmFscy5oU3lzdGVtTWVudSwgQ0xfT05fVE9QLCBNRl9CWUNPTU1BTkQgfCBcCiAgICAgICAgICAgICAgICAgKEdsb2JhbHMuYkFsd2F5c09uVG9wID8gTUZfQ0hFQ0tFRCA6IE1GX1VOQ0hFQ0tFRCkpOwogICAgQ2hlY2tNZW51SXRlbShHbG9iYWxzLmhQcm9wZXJ0aWVzTWVudSwgQ0xfU0VDT05EUywgTUZfQllDT01NQU5EIHwgXAogICAgICAgICAgICAgICAgIChHbG9iYWxzLmJTZWNvbmRzID8gTUZfQ0hFQ0tFRCA6IE1GX1VOQ0hFQ0tFRCkpOwogICAgQ2hlY2tNZW51SXRlbShHbG9iYWxzLmhQcm9wZXJ0aWVzTWVudSwgQ0xfREFURSwgTUZfQllDT01NQU5EIHwgXAogICAgICAgICAgICAgICAgIChHbG9iYWxzLmJEYXRlID8gTUZfQ0hFQ0tFRCA6IE1GX1VOQ0hFQ0tFRCkpOwp9CgpWT0lEIExBTkdVQUdFX1VwZGF0ZVdpbmRvd0NhcHRpb24oVk9JRCkgewoKICBDSEFSIHN6Q2FwdGlvbltNQVhfU1RSSU5HX0xFTl07CiAgQ0hBUiBzekRhdGVbTUFYX1NUUklOR19MRU5dOwogIAogIExQU1RSIGRhdGUgPSBzekRhdGU7CiAgCiAgU1lTVEVNVElNRSBzdDsKICBMUFNZU1RFTVRJTUUgbHBzdCA9ICZzdDsKCiAgR2V0TG9jYWxUaW1lKCZzdCk7CiAgR2V0RGF0ZUZvcm1hdChMT0NBTEVfVVNFUl9ERUZBVUxULCBMT0NBTEVfU0xPTkdEQVRFLCBscHN0LCBOVUxMLCBkYXRlLAogICAgICAgICAgICAgICAgTUFYX1NUUklOR19MRU4pOwoKICAvKiBTZXQgZnJhbWUgY2FwdGlvbiAqLwogIExvYWRTdHJpbmcoR2xvYmFscy5oSW5zdGFuY2UsIElEU19DTE9DSywgc3pDYXB0aW9uLCBzaXplb2Yoc3pDYXB0aW9uKSk7CiAgaWYgKEdsb2JhbHMuYkRhdGUpIHsKICAgICBsc3RyY2F0KHN6Q2FwdGlvbiwgIiAtICIpOwogICAgIGxzdHJjYXQoc3pDYXB0aW9uLCBzekRhdGUpOwogIH0KICBTZXRXaW5kb3dUZXh0KEdsb2JhbHMuaE1haW5XbmQsIHN6Q2FwdGlvbik7Cgp9CgoKCnN0YXRpYyBCT09MIExBTkdVQUdFX0xvYWRTdHJpbmdPdGhlcihVSU5UIG51bSwgVUlOVCBpZHMsIExQU1RSIHN0ciwgVUlOVCBsZW4pCnsKICBpZHMgLT0gR2xvYmFscy53U3RyaW5nVGFibGVPZmZzZXQ7CiAgaWRzICs9IG51bSAqIDB4MTAwOwogIHJldHVybihMb2FkU3RyaW5nKEdsb2JhbHMuaEluc3RhbmNlLCBpZHMsIHN0ciwgbGVuKSk7Cn07CgpWT0lEIExBTkdVQUdFX1NlbGVjdEJ5TmFtZShMUENTVFIgbGFuZykKewogIElOVCBpOwogIENIQVIgc3pOZXdMYW5nWzNdOwoKICBmb3IgKGkgPSAwOyBpIDw9IE1BWF9MQU5HVUFHRV9OVU1CRVI7IGkrKykKICAgIGlmIChMQU5HVUFHRV9Mb2FkU3RyaW5nT3RoZXIoaSwgSURTX0xBTkdVQUdFX0lELCBzek5ld0xhbmcsIAogICAgICAgICAgICAgICAgc2l6ZW9mKHN6TmV3TGFuZykpICYmICFsc3RyY21wKGxhbmcsIHN6TmV3TGFuZykpCiAgICAgIHsKICAgICAgICBMQU5HVUFHRV9TZWxlY3RCeU51bWJlcihpKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgLyogRmFsbGJhY2sgKi8KICAgIGZvciAoaSA9IDA7IGkgPD0gTUFYX0xBTkdVQUdFX05VTUJFUjsgaSsrKQogICAgaWYgKExBTkdVQUdFX0xvYWRTdHJpbmdPdGhlcihpLCBJRFNfTEFOR1VBR0VfSUQsIHN6TmV3TGFuZywgc2l6ZW9mKHN6TmV3TGFuZykpKQogICAgICB7CiAgICAgICAgTEFOR1VBR0VfU2VsZWN0QnlOdW1iZXIoaSk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgTWVzc2FnZUJveChHbG9iYWxzLmhNYWluV25kLCAiTm8gbGFuZ3VhZ2UgZm91bmQiLCAiRkFUQUwgRVJST1IiLCBNQl9PSyk7CiAgICBQb3N0UXVpdE1lc3NhZ2UoMSk7Cn0KClZPSUQgTEFOR1VBR0VfU2VsZWN0QnlOdW1iZXIoVUlOVCBudW0pCnsKICBJTlQgICAgaTsKICBDSEFSICAgc3pMYW5ndWFnZVszXTsKCiAgQ0hBUiAgIHN6SXRlbVtNQVhfU1RSSU5HX0xFTl07CiAgSE1FTlUgIGhNYWluTWVudTsKCiAgLyogU2VsZWN0IHN0cmluZyB0YWJsZSAqLwogIEdsb2JhbHMud1N0cmluZ1RhYmxlT2Zmc2V0ID0gbnVtICogMHgxMDA7CgogIC8qIEdldCBMYW5ndWFnZSBpZCAqLwogIExvYWRTdHJpbmcoR2xvYmFscy5oSW5zdGFuY2UsIElEU19MQU5HVUFHRV9JRCwgc3pMYW5ndWFnZSwgc2l6ZW9mKHN6TGFuZ3VhZ2UpKTsKCiAgLyogQ2hhbmdlIFJlc291cmNlIG5hbWVzICovCiAgbHN0cmNweW4oU1RSSU5HX01FTlVfWHggKyBzaXplb2YoU1RSSU5HX01FTlVfWHgpIC0gMywgc3pMYW5ndWFnZSwgMyk7CgogIC8qIENyZWF0ZSBtZW51ICovCiAgaE1haW5NZW51ID0gTG9hZE1lbnUoR2xvYmFscy5oSW5zdGFuY2UsIFNUUklOR19NRU5VX1h4KTsKICAgIEdsb2JhbHMuaFByb3BlcnRpZXNNZW51ICAgICA9IEdldFN1Yk1lbnUoaE1haW5NZW51LCAwKTsKICAgIEdsb2JhbHMuaExhbmd1YWdlTWVudSAgICAgICA9IEdldFN1Yk1lbnUoaE1haW5NZW51LCAxKTsKICAgIEdsb2JhbHMuaEluZm9NZW51ICAgICAgICAgICA9IEdldFN1Yk1lbnUoaE1haW5NZW51LCAyKTsKCiAgLyogUmVtb3ZlIGR1bW15IGl0ZW0gKi8KICBSZW1vdmVNZW51KEdsb2JhbHMuaExhbmd1YWdlTWVudSwgMCwgTUZfQllQT1NJVElPTik7CiAgLyogQWRkIGxhbmd1YWdlIGl0ZW1zICovCiAgZm9yIChpID0gMDsgaSA8PSBNQVhfTEFOR1VBR0VfTlVNQkVSOyBpKyspCiAgICBpZiAoTEFOR1VBR0VfTG9hZFN0cmluZ090aGVyKGksIElEU19MQU5HVUFHRV9NRU5VX0lURU0sIHN6SXRlbSwgc2l6ZW9mKHN6SXRlbSkpKQogICAgICAgICAgICAgQXBwZW5kTWVudShHbG9iYWxzLmhMYW5ndWFnZU1lbnUsIE1GX1NUUklORyB8IE1GX0JZQ09NTUFORCwKICAgICAgICAgICAgICAgICAgICAgICAgQ0xfRklSU1RfTEFOR1VBR0UgKyBpLCBzekl0ZW0pOwogIEVuYWJsZU1lbnVJdGVtKEdsb2JhbHMuaExhbmd1YWdlTWVudSwgQ0xfRklSU1RfTEFOR1VBR0UgKyBudW0sIE1GX0JZQ09NTUFORCB8IE1GX0NIRUNLRUQpOwoKICBTZXRNZW51KEdsb2JhbHMuaE1haW5XbmQsIGhNYWluTWVudSk7CgogIC8qIERlc3Ryb3kgb2xkIG1lbnUgKi8KICBpZiAoR2xvYmFscy5oTWFpbk1lbnUpIERlc3Ryb3lNZW51KEdsb2JhbHMuaE1haW5NZW51KTsKICBHbG9iYWxzLmhNYWluTWVudSA9IGhNYWluTWVudTsKCiAgLyogc3BlY2lmaWMgZm9yIENsb2NrOiAqLwoKICBMQU5HVUFHRV9VcGRhdGVNZW51Q2hlY2ttYXJrcygpOwogIExBTkdVQUdFX1VwZGF0ZVdpbmRvd0NhcHRpb24oKTsgICAKCiAgR2xvYmFscy5oU3lzdGVtTWVudSA9IEdldFN5c3RlbU1lbnUoR2xvYmFscy5oTWFpblduZCwgVFJVRSk7CgogIC8qIEZJWE1FOiBBcHBlbmQgYSBTRVBBUkFUT1IgdG8gR2xvYmFscy5oU3lzdGVtTWVudSBoZXJlICovCgogIExvYWRTdHJpbmcoR2xvYmFscy5oSW5zdGFuY2UsIElEU19NRU5VX09OX1RPUCwgc3pJdGVtLCBzaXplb2Yoc3pJdGVtKSk7CiAgQXBwZW5kTWVudShHbG9iYWxzLmhTeXN0ZW1NZW51LCBNRl9TVFJJTkcgfCBNRl9CWUNPTU1BTkQsIDEwMDAsIHN6SXRlbSk7Cn0KClZPSUQgTEFOR1VBR0VfRGVmYXVsdEhhbmRsZShXUEFSQU0gd1BhcmFtKQp7CiAgaWYgKCh3UGFyYW0gPj1DTF9GSVJTVF9MQU5HVUFHRSkgJiYgKHdQYXJhbTw9Q0xfTEFTVF9MQU5HVUFHRSkpCiAgICAgICAgICBMQU5HVUFHRV9TZWxlY3RCeU51bWJlcih3UGFyYW0gLSBDTF9GSVJTVF9MQU5HVUFHRSk7CiAgICAgZWxzZSBwcmludGYoIlVuaW1wbGVtZW50ZWQgbWVudSBjb21tYW5kICVpXG4iLCB3UGFyYW0pOwp9CgovKiBMb2NhbCBWYXJpYWJsZXM6ICAgICovCi8qIGMtZmlsZS1zdHlsZTogIkdOVSIgKi8KLyogRW5kOiAgICAgICAgICAgICAgICAqLwo=