LyoKICogKEMpIENvcHlyaWdodCAyMDAyCiAqIERhbmllbCBFbmdzdHL2bSwgT21pY3JvbiBDZXRpIEFCLCA8ZGFuaWVsQG9taWNyb24uc2U+CiAqCiAqIFNlZSBmaWxlIENSRURJVFMgZm9yIGxpc3Qgb2YgcGVvcGxlIHdobyBjb250cmlidXRlZCB0byB0aGlzCiAqIHByb2plY3QuCiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMKICogcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YKICogdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCiAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCiAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sCiAqIE1BIDAyMTExLTEzMDcgVVNBCiAqLwoKI2luY2x1ZGUgPGNvbW1vbi5oPgojaW5jbHVkZSA8cGNpLmg+CiNpbmNsdWRlIDxzdGRpb19kZXYuaD4KI2luY2x1ZGUgPGk4MDQyLmg+CiNpbmNsdWRlIDxhc20vcHRyYWNlLmg+CiNpbmNsdWRlIDxhc20vcmVhbG1vZGUuaD4KI2luY2x1ZGUgPGFzbS9pby5oPgojaW5jbHVkZSA8YXNtL3BjaS5oPgoKLyogYmFzaWMgdGV4dG1vZGUgSS9PIGZyb20gbGludXgga2VybmVsICovCnN0YXRpYyBjaGFyICp2aWRtZW0gPSAoY2hhciAqKTB4YjgwMDA7CnN0YXRpYyBpbnQgdmlkcG9ydDsKc3RhdGljIGludCBsaW5lcywgY29sczsKc3RhdGljIGludCBvcmlnX3gsIG9yaWdfeTsKCnN0YXRpYyB2b2lkIGJlZXAoaW50IGR1cikKewoJaW50IGk7CgoJb3V0Yl9wKDMsIDB4NjEpOwoJZm9yIChpID0gMDsgaSA8IDEwKmR1cjsgaSsrKQoJCXVkZWxheSgxMDAwKTsKCglvdXRiX3AoMCwgMHg2MSk7Cn0KCnN0YXRpYyB2b2lkIHNjcm9sbCh2b2lkKQp7CglpbnQgaTsKCgltZW1jcHkodmlkbWVtLCB2aWRtZW0gKyBjb2xzICogMiwgKGxpbmVzIC0gMSkgKiBjb2xzICogMik7Cglmb3IgKGkgPSAobGluZXMgLSAxKSAqIGNvbHMgKiAyOyBpIDwgbGluZXMgKiBjb2xzICogMjsgaSArPSAyKQoJCXZpZG1lbVtpXSA9ICcgJzsKfQoKc3RhdGljIHZvaWQgX192aWRlb19wdXRjKGNvbnN0IGNoYXIgYywgaW50ICp4LCBpbnQgKnkpCnsKCWlmIChjID09ICdcbicpIHsKCQkoKngpID0gMDsKCQlpZiAoKysoKnkpID49IGxpbmVzKSB7CgkJCXNjcm9sbCgpOwoJCQkoKnkpLS07CgkJfQoJfSBlbHNlIGlmIChjID09ICdcYicpIHsKCQlpZiAoKCp4KSAhPSAwKSB7CgkJCS0tKCp4KTsKCQkJdmlkbWVtWygoKngpICsgY29scyAqICgqeSkpICogMl0gPSAnICc7CgkJfQoJfSBlbHNlIGlmIChjID09ICdccicpIHsKCQkoKngpID0gMDsKCgl9IGVsc2UgaWYgKGMgPT0gJ1xhJykgewoJCWJlZXAoMyk7CgoJfSBlbHNlIGlmIChjID09ICdcdCcpIHsKCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCX0gZWxzZSBpZiAoYyA9PSAnXHYnKSB7CgkJc3dpdGNoICgoKngpICUgOCkgewoJCWNhc2UgMDoKCQkJX192aWRlb19wdXRjKCcgJywgeCwgeSk7CgkJY2FzZSA3OgoJCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQljYXNlIDY6CgkJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCWNhc2UgNToKCQkJX192aWRlb19wdXRjKCcgJywgeCwgeSk7CgkJY2FzZSA0OgoJCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQljYXNlIDM6CgkJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCWNhc2UgMjoKCQkJX192aWRlb19wdXRjKCcgJywgeCwgeSk7CgkJY2FzZSAxOgoJCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQl9Cgl9IGVsc2UgaWYgKGMgPT0gJ1xmJykgewoJCWludCBpOwoJCWZvciAoaSA9IDA7IGkgPCBsaW5lcyAqIGNvbHMgKiAyOyBpICs9IDIpCgkJCXZpZG1lbVtpXSA9IDA7CgkJKCp4KSA9IDA7CgkJKCp5KSA9IDA7Cgl9IGVsc2UgewoJCXZpZG1lbVsoKCp4KSArIGNvbHMgKiAoKnkpKSAqIDJdID0gYzsKCQlpZiAoKysoKngpID49IGNvbHMpIHsKCQkJKCp4KSA9IDA7CgkJCWlmICgrKygqeSkgPj0gbGluZXMpIHsKCQkJCXNjcm9sbCgpOwoJCQkJKCp5KS0tOwoJCQl9CgkJfQoJfQp9CgpzdGF0aWMgdm9pZCB2aWRlb19wdXRjKGNvbnN0IGNoYXIgYykKewoJaW50IHgseSxwb3M7CgoJeCA9IG9yaWdfeDsKCXkgPSBvcmlnX3k7CgoJX192aWRlb19wdXRjKGMsICZ4LCAmeSk7CgoJb3JpZ194ID0geDsKCW9yaWdfeSA9IHk7CgoJcG9zID0gKHggKyBjb2xzICogeSkgKiAyOwkvKiBVcGRhdGUgY3Vyc29yIHBvc2l0aW9uICovCglvdXRiX3AoMTQsIHZpZHBvcnQpOwoJb3V0Yl9wKDB4ZmYgJiAocG9zID4+IDkpLCB2aWRwb3J0KzEpOwoJb3V0Yl9wKDE1LCB2aWRwb3J0KTsKCW91dGJfcCgweGZmICYgKHBvcyA+PiAxKSwgdmlkcG9ydCsxKTsKfQoKc3RhdGljIHZvaWQgdmlkZW9fcHV0cyhjb25zdCBjaGFyICpzKQp7CglpbnQgeCx5LHBvczsKCWNoYXIgYzsKCgl4ID0gb3JpZ194OwoJeSA9IG9yaWdfeTsKCgl3aGlsZSAoKGMgPSAqcysrKSAhPSAnXDAnKQoJCV9fdmlkZW9fcHV0YyhjLCAmeCwgJnkpOwoKCW9yaWdfeCA9IHg7CglvcmlnX3kgPSB5OwoKCXBvcyA9ICh4ICsgY29scyAqIHkpICogMjsJLyogVXBkYXRlIGN1cnNvciBwb3NpdGlvbiAqLwoJb3V0Yl9wKDE0LCB2aWRwb3J0KTsKCW91dGJfcCgweGZmICYgKHBvcyA+PiA5KSwgdmlkcG9ydCsxKTsKCW91dGJfcCgxNSwgdmlkcG9ydCk7CglvdXRiX3AoMHhmZiAmIChwb3MgPj4gMSksIHZpZHBvcnQrMSk7Cn0KCmludCB2aWRlb19pbml0KHZvaWQpCnsKCXUxNiBwb3M7CgoJc3RhdGljIHN0cnVjdCBzdGRpb19kZXYgdmdhX2RldjsKCXN0YXRpYyBzdHJ1Y3Qgc3RkaW9fZGV2IGtiZF9kZXY7CgoJdmlkbWVtID0gKGNoYXIgKikgMHhiODAwMDsKCXZpZHBvcnQgPSAweDNkNDsKCglsaW5lcyA9IDI1OwoJY29scyA9IDgwOwoKCW91dGJfcCgxNCwgdmlkcG9ydCk7Cglwb3MgPSBpbmJfcCh2aWRwb3J0KzEpOwoJcG9zIDw8PSA4OwoJb3V0Yl9wKDE1LCB2aWRwb3J0KTsKCXBvcyB8PSBpbmJfcCh2aWRwb3J0KzEpOwoKCW9yaWdfeCA9IHBvcyVjb2xzOwoJb3JpZ195ID0gcG9zL2NvbHM7CgojaWYgMAoJcHJpbnRmKCJwb3MgJXggJWQgJWRcbiIsIHBvcywgb3JpZ194LCBvcmlnX3kpOwojZW5kaWYKCWlmIChvcmlnX3kgPiBsaW5lcykKCQlvcmlnX3ggPSBvcmlnX3kgPTA7CgoJbWVtc2V0KCZ2Z2FfZGV2LCAwLCBzaXplb2YodmdhX2RldikpOwoJc3RyY3B5KHZnYV9kZXYubmFtZSwgInZnYSIpOwoJdmdhX2Rldi5leHQgICA9IDA7Cgl2Z2FfZGV2LmZsYWdzID0gREVWX0ZMQUdTX09VVFBVVCB8IERFVl9GTEFHU19TWVNURU07Cgl2Z2FfZGV2LnB1dGMgID0gdmlkZW9fcHV0YzsgICAgICAgIC8qICdwdXRjJyBmdW5jdGlvbiAqLwoJdmdhX2Rldi5wdXRzICA9IHZpZGVvX3B1dHM7ICAgICAgICAvKiAncHV0cycgZnVuY3Rpb24gKi8KCXZnYV9kZXYudHN0YyAgPSBOVUxMOyAgICAgICAgICAgICAgLyogJ3RzdGMnIGZ1bmN0aW9uICovCgl2Z2FfZGV2LmdldGMgID0gTlVMTDsgICAgICAgICAgICAgIC8qICdnZXRjJyBmdW5jdGlvbiAqLwoKCWlmIChzdGRpb19yZWdpc3RlcigmdmdhX2RldikgPT0gMCkKCQlyZXR1cm4gMTsKCglpZiAoaTgwNDJfa2JkX2luaXQoKSkKCQlyZXR1cm4gMTsKCgltZW1zZXQoJmtiZF9kZXYsIDAsIHNpemVvZihrYmRfZGV2KSk7CglzdHJjcHkoa2JkX2Rldi5uYW1lLCAia2JkIik7CglrYmRfZGV2LmV4dCAgID0gMDsKCWtiZF9kZXYuZmxhZ3MgPSBERVZfRkxBR1NfSU5QVVQgfCBERVZfRkxBR1NfU1lTVEVNOwoJa2JkX2Rldi5wdXRjICA9IE5VTEw7ICAgICAgICAvKiAncHV0YycgZnVuY3Rpb24gKi8KCWtiZF9kZXYucHV0cyAgPSBOVUxMOyAgICAgICAgLyogJ3B1dHMnIGZ1bmN0aW9uICovCglrYmRfZGV2LnRzdGMgID0gaTgwNDJfdHN0YzsgIC8qICd0c3RjJyBmdW5jdGlvbiAqLwoJa2JkX2Rldi5nZXRjICA9IGk4MDQyX2dldGM7ICAvKiAnZ2V0YycgZnVuY3Rpb24gKi8KCglpZiAoc3RkaW9fcmVnaXN0ZXIoJmtiZF9kZXYpID09IDApCgkJcmV0dXJuIDE7CgoJcmV0dXJuIDA7Cn0KCgppbnQgZHJ2X3ZpZGVvX2luaXQodm9pZCkKewoJaWYgKHZpZGVvX2Jpb3NfaW5pdCgpKQoJCXJldHVybiAxOwoKCXJldHVybiB2aWRlb19pbml0KCk7Cn0K