LyoKICogKEMpIENvcHlyaWdodCAyMDAyCiAqIERhbmllbCBFbmdzdHL2bSwgT21pY3JvbiBDZXRpIEFCLCBkYW5pZWxAb21pY3Jvbi5zZQogKgogKiBTZWUgZmlsZSBDUkVESVRTIGZvciBsaXN0IG9mIHBlb3BsZSB3aG8gY29udHJpYnV0ZWQgdG8gdGhpcwogKiBwcm9qZWN0LgogKgogKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzCiAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mCiAqIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQogKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQogKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLAogKiBNQSAwMjExMS0xMzA3IFVTQQogKi8KCiNpbmNsdWRlIDxjb21tb24uaD4KI2luY2x1ZGUgPHBjaS5oPgojaW5jbHVkZSA8ZGV2aWNlcy5oPgojaW5jbHVkZSA8aTgwNDIuaD4KI2luY2x1ZGUgPGFzbS9wdHJhY2UuaD4KI2luY2x1ZGUgPGFzbS9yZWFsbW9kZS5oPgojaW5jbHVkZSA8YXNtL2lvLmg+CiNpbmNsdWRlIDxhc20vcGNpLmg+CgoKLyogYmFzaWMgdGV4dG1vZGUgSS9PIGZyb20gbGludXgga2VybmVsICovCnN0YXRpYyBjaGFyICp2aWRtZW0gPSAoY2hhciAqKTB4YjgwMDA7CnN0YXRpYyBpbnQgdmlkcG9ydDsKc3RhdGljIGludCBsaW5lcywgY29sczsKc3RhdGljIGludCBvcmlnX3gsIG9yaWdfeTsKCnN0YXRpYyB2b2lkIGJlZXAoaW50IGR1cikKewoJaW50IGk7CgoJb3V0Yl9wKDMsIDB4NjEpOwoJZm9yIChpPTA7aTwxMCpkdXI7aSsrKSB7CgkJdWRlbGF5KDEwMDApOwoJfQoJb3V0Yl9wKDAsIDB4NjEpOwp9CgpzdGF0aWMgdm9pZCBzY3JvbGwodm9pZCkKewoJaW50IGk7CgoJbWVtY3B5ICggdmlkbWVtLCB2aWRtZW0gKyBjb2xzICogMiwgKCBsaW5lcyAtIDEgKSAqIGNvbHMgKiAyICk7Cglmb3IgKCBpID0gKCBsaW5lcyAtIDEgKSAqIGNvbHMgKiAyOyBpIDwgbGluZXMgKiBjb2xzICogMjsgaSArPSAyICkKCQl2aWRtZW1baV0gPSAnICc7Cn0KCnN0YXRpYyB2b2lkIF9fdmlkZW9fcHV0Yyhjb25zdCBjaGFyIGMsIGludCAqeCwgaW50ICp5KQp7CglpZiAoYyA9PSAnXG4nKSB7CgkJKCp4KSA9IDA7CgkJaWYgKCArKygqeSkgPj0gbGluZXMgKSB7CgkJCXNjcm9sbCgpOwoJCQkoKnkpLS07CgkJfQoJfSBlbHNlIGlmIChjID09ICdcYicpIHsKCQlpZiAoKCp4KSAhPSAwKSB7CgkJCS0tKCp4KTsKCQkJdmlkbWVtIFsgKCAoKngpICsgY29scyAqICgqeSkgKSAqIDIgXSA9ICcgJzsKCQl9Cgl9IGVsc2UgaWYgKGMgPT0gJ1xyJykgewoJCSgqeCkgPSAwOwoKCX0gZWxzZSBpZiAoYyA9PSAnXGEnKSB7CgkJYmVlcCgzKTsKCgl9IGVsc2UgaWYgKGMgPT0gJ1x0JykgewoJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJfSBlbHNlIGlmIChjID09ICdcdicpIHsKCQlzd2l0Y2ggKCgqeCkgJSA4KSB7CgkJY2FzZSAwOgoJCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQljYXNlIDc6CgkJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCWNhc2UgNjoKCQkJX192aWRlb19wdXRjKCcgJywgeCwgeSk7CgkJY2FzZSA1OgoJCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQljYXNlIDQ6CgkJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCWNhc2UgMzoKCQkJX192aWRlb19wdXRjKCcgJywgeCwgeSk7CgkJY2FzZSAyOgoJCQlfX3ZpZGVvX3B1dGMoJyAnLCB4LCB5KTsKCQljYXNlIDE6CgkJCV9fdmlkZW9fcHV0YygnICcsIHgsIHkpOwoJCX0KCX0gZWxzZSBpZiAoYyA9PSAnXGYnKSB7CgkJaW50IGk7CgkJZm9yIChpPTA7aTxsaW5lcypjb2xzKjI7aSs9MikgewoJCQl2aWRtZW1baV0gPSAwOwoJCX0KCQkoKngpID0gMDsKCQkoKnkpID0gMDsKCX0gZWxzZSB7CgkJdmlkbWVtIFsgKCAoKngpICsgY29scyAqICgqeSkgKSAqIDIgXSA9IGM7CgkJaWYgKCArKygqeCkgPj0gY29scyApIHsKCQkJKCp4KSA9IDA7CgkJCWlmICggKysoKnkpID49IGxpbmVzICkgewoJCQkJc2Nyb2xsKCk7CgkJCQkoKnkpLS07CgkJCX0KCQl9Cgl9Cn0KCnN0YXRpYyB2b2lkIHZpZGVvX3B1dGMoY29uc3QgY2hhciBjKQp7CglpbnQgeCx5LHBvczsKCgl4ID0gb3JpZ194OwoJeSA9IG9yaWdfeTsKCglfX3ZpZGVvX3B1dGMoYywgJngsICZ5KTsKCglvcmlnX3ggPSB4OwoJb3JpZ195ID0geTsKCglwb3MgPSAoeCArIGNvbHMgKiB5KSAqIDI7CS8qIFVwZGF0ZSBjdXJzb3IgcG9zaXRpb24gKi8KCW91dGJfcCgxNCwgdmlkcG9ydCk7CglvdXRiX3AoMHhmZiAmIChwb3MgPj4gOSksIHZpZHBvcnQrMSk7CglvdXRiX3AoMTUsIHZpZHBvcnQpOwoJb3V0Yl9wKDB4ZmYgJiAocG9zID4+IDEpLCB2aWRwb3J0KzEpOwp9CgpzdGF0aWMgdm9pZCB2aWRlb19wdXRzKGNvbnN0IGNoYXIgKnMpCnsKCWludCB4LHkscG9zOwoJY2hhciBjOwoKCXggPSBvcmlnX3g7Cgl5ID0gb3JpZ195OwoKCXdoaWxlICggKCBjID0gKnMrKyApICE9ICdcMCcgKSB7CgkJX192aWRlb19wdXRjKGMsICZ4LCAmeSk7Cgl9CgoJb3JpZ194ID0geDsKCW9yaWdfeSA9IHk7CgoJcG9zID0gKHggKyBjb2xzICogeSkgKiAyOwkvKiBVcGRhdGUgY3Vyc29yIHBvc2l0aW9uICovCglvdXRiX3AoMTQsIHZpZHBvcnQpOwoJb3V0Yl9wKDB4ZmYgJiAocG9zID4+IDkpLCB2aWRwb3J0KzEpOwoJb3V0Yl9wKDE1LCB2aWRwb3J0KTsKCW91dGJfcCgweGZmICYgKHBvcyA+PiAxKSwgdmlkcG9ydCsxKTsKfQoKaW50IHZpZGVvX2luaXQodm9pZCkKewoJdTE2IHBvczsKCglzdGF0aWMgZGV2aWNlX3QgdmdhX2RldjsKCXN0YXRpYyBkZXZpY2VfdCBrYmRfZGV2OwoKCXZpZG1lbSA9IChjaGFyICopIDB4YjgwMDA7Cgl2aWRwb3J0ID0gMHgzZDQ7CgoJbGluZXMgPSAyNTsKCWNvbHMgPSA4MDsKCglvdXRiX3AoMTQsIHZpZHBvcnQpOwoJcG9zID0gaW5iX3AodmlkcG9ydCsxKTsKCXBvcyA8PD0gODsKCW91dGJfcCgxNSwgdmlkcG9ydCk7Cglwb3MgfD0gaW5iX3AodmlkcG9ydCsxKTsKCglvcmlnX3ggPSBwb3MlY29sczsKCW9yaWdfeSA9IHBvcy9jb2xzOwoKI2lmIDAKCXByaW50ZigicG9zICV4ICVkICVkXG4iLCBwb3MsIG9yaWdfeCwgb3JpZ195KTsKI2VuZGlmCglpZiAob3JpZ195ID4gbGluZXMpIHsKCQlvcmlnX3ggPSBvcmlnX3kgPTA7Cgl9CgoKCW1lbXNldCgmdmdhX2RldiwgMCwgc2l6ZW9mKHZnYV9kZXYpKTsKCXN0cmNweSh2Z2FfZGV2Lm5hbWUsICJ2Z2EiKTsKCXZnYV9kZXYuZXh0ICAgPSAwOwoJdmdhX2Rldi5mbGFncyA9IERFVl9GTEFHU19PVVRQVVQgfCBERVZfRkxBR1NfU1lTVEVNOwoJdmdhX2Rldi5wdXRjICA9IHZpZGVvX3B1dGM7ICAgICAgICAvKiAncHV0YycgZnVuY3Rpb24gKi8KCXZnYV9kZXYucHV0cyAgPSB2aWRlb19wdXRzOyAgICAgICAgLyogJ3B1dHMnIGZ1bmN0aW9uICovCgl2Z2FfZGV2LnRzdGMgID0gTlVMTDsgICAgICAgICAgICAgIC8qICd0c3RjJyBmdW5jdGlvbiAqLwoJdmdhX2Rldi5nZXRjICA9IE5VTEw7ICAgICAgICAgICAgICAvKiAnZ2V0YycgZnVuY3Rpb24gKi8KCglpZiAoZGV2aWNlX3JlZ2lzdGVyKCZ2Z2FfZGV2KSA9PSAwKSB7CgkgICAgcmV0dXJuIDE7Cgl9CgoJaWYgKGk4MDQyX2tiZF9pbml0KCkpIHsKCQlyZXR1cm4gMTsKCX0KCgltZW1zZXQoJmtiZF9kZXYsIDAsIHNpemVvZihrYmRfZGV2KSk7CglzdHJjcHkoa2JkX2Rldi5uYW1lLCAia2JkIik7CglrYmRfZGV2LmV4dCAgID0gMDsKCWtiZF9kZXYuZmxhZ3MgPSBERVZfRkxBR1NfSU5QVVQgfCBERVZfRkxBR1NfU1lTVEVNOwoJa2JkX2Rldi5wdXRjICA9IE5VTEw7ICAgICAgICAvKiAncHV0YycgZnVuY3Rpb24gKi8KCWtiZF9kZXYucHV0cyAgPSBOVUxMOyAgICAgICAgLyogJ3B1dHMnIGZ1bmN0aW9uICovCglrYmRfZGV2LnRzdGMgID0gaTgwNDJfdHN0YzsgIC8qICd0c3RjJyBmdW5jdGlvbiAqLwoJa2JkX2Rldi5nZXRjICA9IGk4MDQyX2dldGM7ICAvKiAnZ2V0YycgZnVuY3Rpb24gKi8KCglpZiAoZGV2aWNlX3JlZ2lzdGVyKCZrYmRfZGV2KSA9PSAwKSB7CgkgICAgcmV0dXJuIDE7Cgl9CglyZXR1cm4gMDsKfQoKCmludCBkcnZfdmlkZW9faW5pdCh2b2lkKQp7CglpZiAodmlkZW9fYmlvc19pbml0KCkpIHsKCQlyZXR1cm4gMTsKCX0KCglyZXR1cm4gdmlkZW9faW5pdCgpOwp9Cg==