IwojIGJpbmhleHRyZWUgLSBSZWN1cnNpdmVseSBkZXNjZW5kIGEgZGlyZWN0b3J5IGFuZAojIHBhY2sgYWxsIHJlc291cmNlIGZpbGVzLgojCiMgSmFjayBKYW5zZW4sIENXSSwgQXVndXN0IDE5OTUuCiMKCmltcG9ydCBvcwppbXBvcnQgYmluaGV4CmltcG9ydCBzeXMKaW1wb3J0IG1hY29zdG9vbHMKaW1wb3J0IG1hY2ZzCgppbXBvcnQgYWV0b29scwpmcm9tIE1ldHJvd2Vya3NfU2hlbGxfU3VpdGUgaW1wb3J0IE1ldHJvd2Vya3NfU2hlbGxfU3VpdGUKZnJvbSBSZXF1aXJlZF9TdWl0ZSBpbXBvcnQgUmVxdWlyZWRfU3VpdGUgCgpjbGFzcyBNd1NoZWxsKGFldG9vbHMuVGFsa1RvLCBNZXRyb3dlcmtzX1NoZWxsX1N1aXRlLCBSZXF1aXJlZF9TdWl0ZSk6CglwYXNzCgojIFRvcC1sZXZlbCBkaXJlY3RvcnkKVE9QPScnCgojIFdoZXJlIHRvIHB1dCBDVyBwcm9qZWN0cywgcmVsYXRpdmUgdG8gVE9QCkNXRElSPSc6TWFjOm13ZXJrczpwcm9qZWN0cycKIyBGcm9tIHdoaWNoIGZvbGRlcnMgdG8gcHV0IHByb2plY3RzIHRoZXJlCkNXRElSRElSUz1bJ2J1aWxkLm1hYycsICdidWlsZC5tYWNzdGFuZCcsICdQbHVnSW5zJ10KCiMgSGVscGVyIHJvdXRpbmVzCmRlZiBiaW5oZXhpdChwYXRoLCBuYW1lKToKCWRzdGZpbGUgPSBwYXRoICsgJy5ocXgnCglpZiBvcy5wYXRoLmV4aXN0cyhkc3RmaWxlKToKCQlwcmludCAnQ29tcGFyZScsIHBhdGgsJy4uLicsCgkJaWYgYmluaGV4Y29tcGFyZShwYXRoLCBkc3RmaWxlKToKCQkJcHJpbnQgJ0lkZW50aWNhbCwgc2tpcHBlZC4nCgkJCXJldHVybgoJCWVsc2U6CgkJCXByaW50ICdOb3QgdXAtdG8tZGF0ZS4nCglwcmludCAnQmluaGV4aW5nJywgcGF0aAoJYmluaGV4LmJpbmhleChwYXRoLCBkc3RmaWxlKQoJCmRlZiBiaW5oZXhjb21wYXJlKHNvdXJjZSwgaHF4ZmlsZSk6CgkiIiIoc291cmNlLCBocXhmaWxlKSAtIENoZWNrIHdoZXRoZXIgdGhlIHR3byBmaWxlcyBtYXRjaCAoZm9ya3Mgb25seSkiIiIKCWlmcCA9IGJpbmhleC5IZXhCaW4oaHF4ZmlsZSkKCglzZnAgPSBvcGVuKHNvdXJjZSwgJ3JiJykKCXdoaWxlIDE6CgkJZCA9IGlmcC5yZWFkKDEyODAwMCkKCQlkMiA9IHNmcC5yZWFkKDEyODAwMCkKCQlpZiBkIDw+IGQyOgoJCQlyZXR1cm4gMAoJCWlmIG5vdCBkOiBicmVhawoJc2ZwLmNsb3NlKCkKCWlmcC5jbG9zZV9kYXRhKCkKCQoJZCA9IGlmcC5yZWFkX3JzcmMoMTI4MDAwKQoJaWYgZDoKCQlzZnAgPSBiaW5oZXgub3BlbnJzcmMoc291cmNlLCAncmInKQoJCWQyID0gc2ZwLnJlYWQoMTI4MDAwKQoJCWlmIGQgPD4gZDI6CgkJCXJldHVybiAwCgkJd2hpbGUgMToKCQkJZCA9IGlmcC5yZWFkX3JzcmMoMTI4MDAwKQoJCQlkMiA9IHNmcC5yZWFkKDEyODAwMCkKCQkJaWYgZCA8PiBkMjoKCQkJCXJldHVybiAwCgkJCWlmIG5vdCBkOiBicmVhawoJcmV0dXJuIDEKCiMgUHJvamVjdCBmaWxlcyB0byBoYW5kbGUKcHJvamVjdF9maWxlcyA9IHt9CgpkZWYgaGV4YmluY3dwcm9qZWN0cyhjcmVhdG9yKToKCSIiIkNvbXBhY3QgYW5kIGhleGJpbiBhbGwgZmlsZXMgcmVtZW1iZXJlZCB3aXRoIGEgZ2l2ZW4gY3JlYXRvciIiIgoJY3dfcnVubmluZyA9IDAKCWZvciBmc3MgaW4gcHJvamVjdF9maWxlc1tjcmVhdG9yXToKCQlzcmNmaWxlID0gZnNzLmFzX3BhdGhuYW1lKCkKCQkKCQlvbGRfc3R5bGUgPSAwCgkJaWYgc3JjZmlsZVstMV0gPT0gJ7UnOgoJCQlkc3RmaWxlID0gc3JjZmlsZVs6LTFdKydtdS5ocXgnCgkJCW9sZF9zdHlsZSA9IDEKCQllbGlmIHNyY2ZpbGVbLTNdID09ICcubXUnOgoJCQlkc3RmaWxlID0gc3JjZmlsZSArICcuaHF4JwoJCWVsaWYgb3JkKHNyY2ZpbGVbLTFdKSA+PSAxMjg6CgkJCWRzdGZpbGUgPSBzcmNmaWxlWzotMV0rYG9yZChzcmNmaWxlWy0xXSlgKycuaHF4JwoJCWVsc2U6CgkJCWRzdGZpbGUgPSBzcmNmaWxlICsgJy5ocXgnCgkJCQoJCWlmIG9zLnBhdGguZXhpc3RzKGRzdGZpbGUpIGFuZCBcCgkJCQlvcy5zdGF0KGRzdGZpbGUpWzhdID49IG9zLnN0YXQoc3JjZmlsZSlbOF06CgkJCXByaW50ICdTa2lwJywgZHN0ZmlsZSwnLSBVcC10by1kYXRlJwoJCQljb250aW51ZQoJCXByaW50ICdDb21wYWN0aW5nJywgZHN0ZmlsZQoJCWlmIG9sZF9zdHlsZToKCQkJaWYgbm90IGN3X3J1bm5pbmc6CgkJCQl0cnk6CgkJCQkJbWdyID0gTXdTaGVsbChjcmVhdG9yLCBzdGFydD0xKQoJCQkJZXhjZXB0ICdmb28nOgoJCQkJCXByaW50ICdOb3QgaGFuZGxlZDonLCBjcmVhdG9yCgkJCQkJcmV0dXJuCgkJCQljd19ydW5uaW5nID0gMQoJCQltZ3Iub3Blbihmc3MpCgkJCW1nci5SZXNldF9GaWxlX1BhdGhzKCkKCQkJbWdyLlJlbW92ZV9CaW5hcmllcygpCgkJCW1nci5DbG9zZV9Qcm9qZWN0KCkKCQkKCQlwcmludCAnQmluaGV4aW5nJywgZHN0ZmlsZQoJCWJpbmhleC5iaW5oZXgoc3JjZmlsZSwgZHN0ZmlsZSkKCWlmIGN3X3J1bm5pbmc6CgkJbWdyLnF1aXQoKQoJCmRlZiBjb3B5Y3dwcm9qZWN0KHBhdGgsIG5hbWUpOgoJIiIiQ29weSBDVyBwcm9qZWN0IChpZiBuZWVkZWQpIGFuZCByZW1lbWJlciBmb3IgaGV4YmlubmluZyIiIgoJZ2xvYmFsIHByb2plY3RfZmlsZXMKCQoJZHN0ZGlyID0gb3MucGF0aC5qb2luKFRPUCwgQ1dESVIpCglpZiBwYXRoWzpsZW4oZHN0ZGlyKV0gPT0gZHN0ZGlyOgoJCXJldHVybgoJc3JjZGlyID0gb3MucGF0aC5zcGxpdChwYXRoKVswXQoJc3JjZGlyID0gb3MucGF0aC5zcGxpdChzcmNkaXIpWzFdCglpZiBzcmNkaXIgaW4gQ1dESVJESVJTOgoJCWlmIG5vdCBvcy5wYXRoLmV4aXN0cyhkc3RkaXIpOgoJCQlwcmludCBkc3RkaXIKCQkJcHJpbnQgJ05vIENXLXByb2plY3QgZGlyLCBza2lwJywgbmFtZQoJCQlyZXR1cm4KCQlkc3RmaWxlID0gb3MucGF0aC5qb2luKGRzdGRpciwgb3MucGF0aC5qb2luKHNyY2RpciwgbmFtZSkpCgllbHNlOgoJCWlmIHBhdGhbLTI6XSA9PSAnLrUnOgoJCQlkc3RmaWxlID0gcGF0aFs6LTJdKyAnLm11JwoJCWVsaWYgcGF0aFstNDpdID09ICcucHJqJzoKCQkJZHN0ZmlsZSA9IE5vbmUKCQllbHNlOgoJCQlyZXR1cm4KCglpZiBkc3RmaWxlOgoJCSMgSWYgdGhlIGRlc3RpbmF0aW9uIGRvZXNuJ3QgZXhpc3RzIG9yIGlzIG9sZGVyIHRoYXQgdGhlIHNvdXJjZQoJCSMgd2UgY29weSBhbmQgcmVtZW1iZXIgaXQKCQkKCQlpZiBvcy5wYXRoLmV4aXN0cyhkc3RmaWxlKSBhbmQgXAoJCQkJb3Muc3RhdChkc3RmaWxlKVs4XSA+PSBvcy5zdGF0KHBhdGgpWzhdOgoJCQlwcmludCAnTm90IGNvcHlpbmcnLCBwYXRoLCctIFVwLXRvLWRhdGUnCgkJZWxzZToKCQkJcHJpbnQgJ0NvcHknLCBwYXRoCgkJCW1hY29zdG9vbHMuY29weShwYXRoLCBkc3RmaWxlKQoJZWxzZToKCQlkc3RmaWxlID0gcGF0aAoJCglmc3MgPSBtYWNmcy5GU1NwZWMoZHN0ZmlsZSkKCWNyZWF0b3IgPSBmc3MuR2V0Q3JlYXRvclR5cGUoKVswXQoJCglpZiBwcm9qZWN0X2ZpbGVzLmhhc19rZXkoY3JlYXRvcik6CgkJcHJvamVjdF9maWxlc1tjcmVhdG9yXS5hcHBlbmQoZnNzKQoJZWxzZToKCQlwcm9qZWN0X2ZpbGVzW2NyZWF0b3JdID0gW2Zzc10JCgkKZGVmIGNvcHljd2V4cGZpbGUocGF0aCwgbmFtZSk6CgkiIiJDb3B5IENXIGV4cG9ydCBmaWxlIiIiCglnbG9iYWwgcHJvamVjdF9maWxlcwoJCglkc3RkaXIgPSBvcy5wYXRoLmpvaW4oVE9QLCBDV0RJUikKCWlmIHBhdGhbOmxlbihkc3RkaXIpXSA9PSBkc3RkaXI6CgkJcmV0dXJuCglzcmNkaXIgPSBvcy5wYXRoLnNwbGl0KHBhdGgpWzBdCglzcmNkaXIgPSBvcy5wYXRoLnNwbGl0KHNyY2RpcilbMV0KCWlmIHNyY2RpciBpbiBDV0RJUkRJUlM6CgkJaWYgbm90IG9zLnBhdGguZXhpc3RzKGRzdGRpcik6CgkJCXByaW50IGRzdGRpcgoJCQlwcmludCAnTm8gQ1ctcHJvamVjdCBkaXIsIHNraXAnLCBuYW1lCgkJCXJldHVybgoJCWRzdGZpbGUgPSBvcy5wYXRoLmpvaW4oZHN0ZGlyLCBvcy5wYXRoLmpvaW4oc3JjZGlyLCBuYW1lKSkKCWVsc2U6CgkJaWYgcGF0aFstNjpdICE9ICcutS5leHAnOgoJCQlyZXR1cm4KCQlkc3RmaWxlID0gcGF0aFs6LTZdICsgJy5tdS5leHAnCglpZiBkc3RmaWxlWy02Ol0gPT0gJy61LmV4cCc6CgkJZHN0ZmlsZSA9IGRzdGZpbGVbOi02XSsnLm11LmV4cCcKCgkjIElmIHRoZSBkZXN0aW5hdGlvbiBkb2Vzbid0IGV4aXN0cyBvciBpcyBvbGRlciB0aGF0IHRoZSBzb3VyY2UKCSMgd2UgY29weSBhbmQgcmVtZW1iZXIgaXQKCQoJaWYgb3MucGF0aC5leGlzdHMoZHN0ZmlsZSkgYW5kIFwKCQkJb3Muc3RhdChkc3RmaWxlKVs4XSA+PSBvcy5zdGF0KHBhdGgpWzhdOgoJCXByaW50ICdOb3QgY29weWluZycsIHBhdGgsJy0gVXAtdG8tZGF0ZScKCWVsc2U6CgkJcHJpbnQgJ0NvcHknLCBwYXRoCgkJbWFjb3N0b29scy5jb3B5KHBhdGgsIGRzdGZpbGUpCQoKZXh0ZW5zaW9ucyA9IFsKCSgnLnJzcmMnLCBiaW5oZXhpdCksCgkoJy5naWYnLCBiaW5oZXhpdCksCgkoJy61JywgY29weWN3cHJvamVjdCksCgkoJy5wcmonLCBjb3B5Y3dwcm9qZWN0KSwKCSgnLnByai5leHAnLCBjb3B5Y3dleHBmaWxlKSwKCSgnLrUuZXhwJywgY29weWN3ZXhwZmlsZSkKCV0KCmRlZiB3YWxrZXIoYXJnLCB0b3AsIG5hbWVzKToKCWxuYW1lcyA9IG5hbWVzWzpdCglmb3IgbiBpbiBsbmFtZXM6CgkJaWYgblswXSA9PSAnKCcgYW5kIG5bLTFdID09ICcpJzoKCQkJbmFtZXMucmVtb3ZlKG4pCgkJCWNvbnRpbnVlCgkJZm9yIGV4dCwgaGFuZGxlciBpbiBleHRlbnNpb25zOgoJCQlpZiBuWy1sZW4oZXh0KTpdID09IGV4dDoKCQkJCW5hbWUgPSBvcy5wYXRoLmpvaW4odG9wLCBuKQoJCQkJaGFuZGxlcihuYW1lLCBuKQoJCQkJCmRlZiBkb2RpcihuYW1lKToKCWdsb2JhbCBUT1AsIHByb2plY3RfZmlsZXMKCVRPUCA9IG5hbWUKCW9zLnBhdGgud2FsayhuYW1lLCB3YWxrZXIsIE5vbmUpCgkKCWZvciBjcmVhdG9yIGluIHByb2plY3RfZmlsZXMua2V5cygpOgoJCWhleGJpbmN3cHJvamVjdHMoY3JlYXRvcikKCXByb2plY3RfZmlsZXMgPSB7fQoJCQkJCmRlZiBtYWluKCk6CglpZiBsZW4oc3lzLmFyZ3YpID4gMToKCQlmb3IgZGlyIGluIHN5cy5hcmd2WzE6XToKCQkJZG9kaXIoZGlyKQoJZWxpZiBvcy5uYW1lID09ICdtYWMnOgoJCWltcG9ydCBtYWNmcwoJCWRpciwgb2sgPSBtYWNmcy5HZXREaXJlY3RvcnkoJ0ZvbGRlciB0byBzZWFyY2g6JykKCQlpZiBub3Qgb2s6CgkJCXN5cy5leGl0KDApCgkJZG9kaXIoZGlyLmFzX3BhdGhuYW1lKCkpCgllbHNlOgoJCXByaW50ICdVc2FnZTogaGV4YmludHJlZSBkaXIgLi4uJwoJCXN5cy5leGl0KDEpCglpZiBvcy5uYW1lID09ICdtYWMnOgoJCXN5cy5leGl0KDEpICAgIyBLZWVwIHdpbmRvdwoJZWxzZToKCQlzeXMuZXhpdCgwKQoJCQppZiBfX25hbWVfXyA9PSAnX19tYWluX18nOgoJbWFpbigpCgkK