LyoKICogQ29weXJpZ2h0IChjKSAxOTgwLCAxOTkzCiAqCVRoZSBSZWdlbnRzIG9mIHRoZSBVbml2ZXJzaXR5IG9mIENhbGlmb3JuaWEuICBBbGwgcmlnaHRzIHJlc2VydmVkLgogKgogKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKICogbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zCiAqIGFyZSBtZXQ6CiAqIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0CiAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci4KICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQKICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZQogKiAgICBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLgogKiAzLiBBbGwgYWR2ZXJ0aXNpbmcgbWF0ZXJpYWxzIG1lbnRpb25pbmcgZmVhdHVyZXMgb3IgdXNlIG9mIHRoaXMgc29mdHdhcmUKICogICAgbXVzdCBkaXNwbGF5IHRoZSBmb2xsb3dpbmcgYWNrbm93bGVkZ2VtZW50OgogKglUaGlzIHByb2R1Y3QgaW5jbHVkZXMgc29mdHdhcmUgZGV2ZWxvcGVkIGJ5IHRoZSBVbml2ZXJzaXR5IG9mCiAqCUNhbGlmb3JuaWEsIEJlcmtlbGV5IGFuZCBpdHMgY29udHJpYnV0b3JzLgogKiA0LiBOZWl0aGVyIHRoZSBuYW1lIG9mIHRoZSBVbml2ZXJzaXR5IG5vciB0aGUgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9ycwogKiAgICBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUKICogICAgd2l0aG91dCBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uCiAqCiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIFJFR0VOVFMgQU5EIENPTlRSSUJVVE9SUyBgYEFTIElTJycgQU5ECiAqIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRQogKiBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRQogKiBBUkUgRElTQ0xBSU1FRC4gIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBSRUdFTlRTIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUKICogRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwKICogREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMKICogT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pCiAqIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUCiAqIExJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkKICogT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRgogKiBTVUNIIERBTUFHRS4KICovCgovKgogKiAxOTk5LTAyLTIyIEFya2FkaXVzeiBNabZraWV3aWN6IDxtaXNpZWtAcGxkLk9SRy5QTD4KICogCWFkZGVkIE5hdGl2ZSBMYW5ndWFnZSBTdXBwb3J0CiAqIDE5OTktMDktMTkgQnJ1bm8gSGFpYmxlIDxoYWlibGVAY2xpc3AuY29ucy5vcmc+CiAqIAltb2RpZmllZCB0byB3b3JrIGNvcnJlY3RseSBpbiBtdWx0aS1ieXRlIGxvY2FsZXMKICovCgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8dW5pc3RkLmg+CQkvKiBmb3IgY2xvc2UoKSAqLwojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlICJubHMuaCIKCiNpbmNsdWRlICJ3aWRlY2hhci5oIgoKaW50IHBsdXMod2NoYXJfdCBjLCB3Y2hhcl90IGQpOwp2b2lkIG1vdmUoaW50IGwsIGludCBtKTsKdm9pZCBwZmx1c2goaW50IG9sKTsKCi8qCiAqIGNvbGNydCAtIHJlcGxhY2VzIGNvbCBmb3IgY3J0cyB3aXRoIG5ldyBucm9mZiBlc3AuIHdoZW4gdXNpbmcgdGJsLgogKiBCaWxsIEpveSBVQ0IgSnVseSAxNCwgMTk3NwogKgogKiBUaGlzIGZpbHRlciB1c2VzIGEgc2NyZWVuIGJ1ZmZlciwgMjY3IGhhbGYtbGluZXMgYnkgMTMyIGNvbHVtbnMuCiAqIEl0IGludGVycHJldHMgdGhlIHVwIGFuZCBkb3duIHNlcXVlbmNlcyBnZW5lcmF0ZWQgYnkgdGhlIG5ldwogKiBucm9mZiB3aGVuIHVzZWQgd2l0aCB0YmwgYW5kIGJ5IFx1IFxkIGFuZCBcci4KICogR2VuZXJhbCBvdmVyc3RyaWtpbmcgZG9lc24ndCB3b3JrIGNvcnJlY3RseS4KICogVW5kZXJsaW5pbmcgaXMgc3BsaXQgb250byBtdWx0aXBsZSBsaW5lcywgZXRjLgogKgogKiBPcHRpb24gLSBzdXBwcmVzc2VzIGFsbCB1bmRlcmxpbmluZy4KICogT3B0aW9uIC0yIGZvcmNlcyBwcmludGluZyBvZiBhbGwgaGFsZiBsaW5lcy4KICovCgp3Y2hhcl90CXBhZ2VbMjY3XVsxMzJdOwoKaW50CW91dGxpbmUgPSAxOwppbnQJb3V0Y29sOwoKY2hhcglzdXBwcmVzdWw7CmNoYXIJcHJpbnRhbGw7CgpjaGFyCSpwcm9nbmFtZTsKdm9pZCBjb2xjcnQoRklMRSAqZik7CgppbnQKbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpIHsKCUZJTEUgKmY7CgoJc2V0bG9jYWxlKExDX0FMTCwgIiIpOwoJYmluZHRleHRkb21haW4oUEFDS0FHRSwgTE9DQUxFRElSKTsKCXRleHRkb21haW4oUEFDS0FHRSk7CgoJYXJnYy0tOwoJcHJvZ25hbWUgPSAqYXJndisrOwoJd2hpbGUgKGFyZ2MgPiAwICYmIGFyZ3ZbMF1bMF0gPT0gJy0nKSB7CgkJc3dpdGNoIChhcmd2WzBdWzFdKSB7CgkJCWNhc2UgMDoKCQkJCXN1cHByZXN1bCA9IDE7CgkJCQlicmVhazsKCQkJY2FzZSAnMic6CgkJCQlwcmludGFsbCA9IDE7CgkJCQlicmVhazsKCQkJZGVmYXVsdDoKCQkJCXByaW50ZihfKCJ1c2FnZTogJXMgWyAtIF0gWyAtMiBdIFsgZmlsZSAuLi4gXVxuIiksIHByb2duYW1lKTsKCQkJCWZmbHVzaChzdGRvdXQpOwoJCQkJZXhpdCgxKTsKCQl9CgkJYXJnYy0tOwoJCWFyZ3YrKzsKCX0KCWYgPSBzdGRpbjsKCWRvIHsKCQlpZiAoYXJnYyA+IDApIHsKCQkJaWYgKCEoZiA9IGZvcGVuKGFyZ3ZbMF0sICJyIikpKSB7CgkJCQlmZmx1c2goc3Rkb3V0KTsKCQkJCXBlcnJvcihhcmd2WzBdKTsKCQkJCWV4aXQgKDEpOwoJCQl9CgkJCWFyZ2MtLTsKCQkJYXJndisrOwoJCX0KCQljb2xjcnQoZik7CgkJaWYgKGYgIT0gc3RkaW4pCgkJCWZjbG9zZShmKTsKCX0gd2hpbGUgKGFyZ2MgPiAwKTsKCWZmbHVzaChzdGRvdXQpOwoJaWYgKGZlcnJvcihzdGRvdXQpIHx8IGZjbG9zZShzdGRvdXQpKQoJCXJldHVybiAxOwoJcmV0dXJuIDA7Cn0KCnZvaWQKY29sY3J0KEZJTEUgKmYpIHsKCXdpbnRfdCBjOwoJd2NoYXJfdCAqY3AsICpkcDsKCWludCBpLCB3OwoKCWZvciAoOzspIHsKCQljID0gZ2V0d2MoZik7CgkJaWYgKGMgPT0gV0VPRikgewoJCQlwZmx1c2gob3V0bGluZSk7CgkJCWZmbHVzaChzdGRvdXQpOwoJCQlicmVhazsKCQl9CgkJc3dpdGNoIChjKSB7CgkJY2FzZSAnXG4nOgoJCQlpZiAob3V0bGluZSA+PSAyNjUpCgkJCQlwZmx1c2goNjIpOwoJCQlvdXRsaW5lICs9IDI7CgkJCW91dGNvbCA9IDA7CgkJCWNvbnRpbnVlOwoJCWNhc2UgJ1wwMTYnOgoJCWNhc2UgJ1wwMTcnOgoJCQljb250aW51ZTsKCQljYXNlIDAzMzoKCQkJYyA9IGdldHdjKGYpOwoJCQlzd2l0Y2ggKGMpIHsKCQkJY2FzZSAnOSc6CgkJCQlpZiAob3V0bGluZSA+PSAyNjYpCgkJCQkJcGZsdXNoKDYyKTsKCQkJCW91dGxpbmUrKzsKCQkJCWNvbnRpbnVlOwoJCQljYXNlICc4JzoKCQkJCWlmIChvdXRsaW5lID49IDEpCgkJCQkJb3V0bGluZS0tOwoJCQkJY29udGludWU7CgkJCWNhc2UgJzcnOgoJCQkJb3V0bGluZSAtPSAyOwoJCQkJaWYgKG91dGxpbmUgPCAwKQoJCQkJCW91dGxpbmUgPSAwOwoJCQkJY29udGludWU7CgkJCWRlZmF1bHQ6CgkJCQljb250aW51ZTsKCQkJfQoJCWNhc2UgJ1xiJzoKCQkJaWYgKG91dGNvbCkKCQkJCW91dGNvbC0tOwoJCQljb250aW51ZTsKCQljYXNlICdcdCc6CgkJCW91dGNvbCArPSA4OwoJCQlvdXRjb2wgJj0gfjc7CgkJCW91dGNvbC0tOwoJCQljID0gJyAnOwoJCWRlZmF1bHQ6CgkJCXcgPSB3Y3dpZHRoKGMpOwoJCQlpZiAob3V0Y29sICsgdyA+IDEzMikgewoJCQkJb3V0Y29sKys7CgkJCQljb250aW51ZTsKCQkJfQoJCQljcCA9ICZwYWdlW291dGxpbmVdW291dGNvbF07CgkJCW91dGNvbCArPSB3OwoJCQlpZiAoYyA9PSAnXycpIHsKCQkJCWlmIChzdXBwcmVzdWwpCgkJCQkJY29udGludWU7CgkJCQljcCArPSAxMzI7CgkJCQljID0gJy0nOwoJCQl9CgkJCWlmICgqY3AgPT0gMCkgewoJCQkJLyogdHJpY2shICovCgkJCQlmb3IgKGk9MDsgaTx3OyBpKyspCgkJCQkJY3BbaV0gPSBjOwoJCQkJZHAgPSBjcCAtIChvdXRjb2wtdyk7CgkJCQlmb3IgKGNwLS07IGNwID49IGRwICYmICpjcCA9PSAwOyBjcC0tKQoJCQkJCSpjcCA9ICcgJzsKCQkJfSBlbHNlIHsKCQkJCWlmIChwbHVzKGMsICpjcCkgfHwgcGx1cygqY3AsIGMpKQoJCQkJCSpjcCA9ICcrJzsKCQkJCWVsc2UgaWYgKCpjcCA9PSAnICcgfHwgKmNwID09IDApIHsKCQkJCQlmb3IgKGk9MTsgaTx3OyBpKyspCgkJCQkJCWlmIChjcFtpXSAhPSAnICcgJiYgY3BbaV0gIT0gMCkKCQkJCQkJCWNvbnRpbnVlOwoJCQkJCWZvciAoaT0wOyBpPHc7IGkrKykKCQkJCQkJY3BbaV0gPSBjOwoJCQkJfQoJCQl9CgkJCWNvbnRpbnVlOwoJCX0KCX0KfQoKaW50IHBsdXMod2NoYXJfdCBjLCB3Y2hhcl90IGQpCnsKCglyZXR1cm4gKGMgPT0gJ3wnICYmIChkID09ICctJyB8fCBkID09ICdfJykpOwp9CgppbnQgZmlyc3Q7Cgp2b2lkIHBmbHVzaChpbnQgb2wpCnsKCXJlZ2lzdGVyIGludCBpOwoJcmVnaXN0ZXIgd2NoYXJfdCAqY3A7CgljaGFyIGxhc3RvbWl0OwoJaW50IGwsIHc7CgoJbCA9IG9sOwoJbGFzdG9taXQgPSAwOwoJaWYgKGwgPiAyNjYpCgkJbCA9IDI2NjsKCWVsc2UKCQlsIHw9IDE7Cglmb3IgKGkgPSBmaXJzdCB8IDE7IGkgPCBsOyBpKyspIHsKCQltb3ZlKGksIGkgLSAxKTsKCQltb3ZlKGksIGkgKyAxKTsKCX0KCWZvciAoaSA9IGZpcnN0OyBpIDwgbDsgaSsrKSB7CgkJY3AgPSBwYWdlW2ldOwoJCWlmIChwcmludGFsbCA9PSAwICYmIGxhc3RvbWl0ID09IDAgJiYgKmNwID09IDApIHsKCQkJbGFzdG9taXQgPSAxOwoJCQljb250aW51ZTsKCQl9CgkJbGFzdG9taXQgPSAwOwoJCXdoaWxlICgqY3ApIHsKCQkJaWYgKCh3ID0gd2N3aWR0aCgqY3ApKSA+IDApIHsKCQkJCXB1dHdjaGFyKCpjcCk7CgkJCQljcCArPSB3OwoJCQl9IGVsc2UKCQkJCWNwKys7CgkJfQoJCXB1dHdjaGFyKCdcbicpOwoJfQoJbWVtbW92ZShwYWdlLCBwYWdlW29sXSwgKDI2NyAtIG9sKSAqIDEzMiAqIHNpemVvZih3Y2hhcl90KSk7CgltZW1zZXQocGFnZVsyNjctIG9sXSwgJ1wwJywgb2wgKiAxMzIgKiBzaXplb2Yod2NoYXJfdCkpOwoJb3V0bGluZSAtPSBvbDsKCW91dGNvbCA9IDA7CglmaXJzdCA9IDE7Cn0KCnZvaWQgbW92ZShpbnQgbCwgaW50IG0pCnsKCXJlZ2lzdGVyIHdjaGFyX3QgKmNwLCAqZHA7CgoJZm9yIChjcCA9IHBhZ2VbbF0sIGRwID0gcGFnZVttXTsgKmNwOyBjcCsrLCBkcCsrKSB7CgkJc3dpdGNoICgqY3ApIHsKCQkJY2FzZSAnfCc6CgkJCQlpZiAoKmRwICE9ICcgJyAmJiAqZHAgIT0gJ3wnICYmICpkcCAhPSAwKQoJCQkJCXJldHVybjsKCQkJCWJyZWFrOwoJCQljYXNlICcgJzoKCQkJCWJyZWFrOwoJCQlkZWZhdWx0OgoJCQkJcmV0dXJuOwoJCX0KCX0KCWlmICgqY3AgPT0gMCkgewoJCWZvciAoY3AgPSBwYWdlW2xdLCBkcCA9IHBhZ2VbbV07ICpjcDsgY3ArKywgZHArKykKCQkJaWYgKCpjcCA9PSAnfCcpCgkJCQkqZHAgPSAnfCc7CgkJCWVsc2UgaWYgKCpkcCA9PSAwKQoJCQkJKmRwID0gJyAnOwoJCXBhZ2VbbF1bMF0gPSAwOwoJfQp9Cg==