LyogQm9vc3QgaW50ZXJ2YWwvcm91bmRlZF9hcml0aC5ocHAgdGVtcGxhdGUgaW1wbGVtZW50YXRpb24gZmlsZQogKgogKiBDb3B5cmlnaHQgMjAwMi0yMDAzIEhlcnbpIEJy9m5uaW1hbm4sIEd1aWxsYXVtZSBNZWxxdWlvbmQsIFN5bHZhaW4gUGlvbgogKgogKiBEaXN0cmlidXRlZCB1bmRlciB0aGUgQm9vc3QgU29mdHdhcmUgTGljZW5zZSwgVmVyc2lvbiAxLjAuCiAqIChTZWUgYWNjb21wYW55aW5nIGZpbGUgTElDRU5TRV8xXzAudHh0IG9yCiAqIGNvcHkgYXQgaHR0cDovL3d3dy5ib29zdC5vcmcvTElDRU5TRV8xXzAudHh0KQogKi8KCiNpZm5kZWYgQk9PU1RfTlVNRVJJQ19JTlRFUlZBTF9ST1VOREVEX0FSSVRIX0hQUAojZGVmaW5lIEJPT1NUX05VTUVSSUNfSU5URVJWQUxfUk9VTkRFRF9BUklUSF9IUFAKCiNpbmNsdWRlIDxib29zdC9udW1lcmljL2ludGVydmFsL3JvdW5kaW5nLmhwcD4KI2luY2x1ZGUgPGJvb3N0L251bWVyaWMvaW50ZXJ2YWwvZGV0YWlsL2J1Z3MuaHBwPgojaW5jbHVkZSA8Ym9vc3QvY29uZmlnL25vX3RyMS9jbWF0aC5ocHA+CgpuYW1lc3BhY2UgYm9vc3QgewpuYW1lc3BhY2UgbnVtZXJpYyB7Cm5hbWVzcGFjZSBpbnRlcnZhbF9saWIgewoKLyoKICogVGhyZWUgY2xhc3NlcyBvZiByb3VuZGluZzogZXhhY3QsIHN0ZCwgb3BwCiAqIFNlZSBkb2N1bWVudGF0aW9uIGZvciBkZXRhaWxzLgogKi8KCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFJvdW5kaW5nPgpzdHJ1Y3Qgcm91bmRlZF9hcml0aF9leGFjdDogUm91bmRpbmcgewogIHZvaWQgaW5pdCgpIHsgfQogIHRlbXBsYXRlPGNsYXNzIFU+IFQgY29udl9kb3duKFUgY29uc3QgJnYpIHsgcmV0dXJuIHY7IH0KICB0ZW1wbGF0ZTxjbGFzcyBVPiBUIGNvbnZfdXAgIChVIGNvbnN0ICZ2KSB7IHJldHVybiB2OyB9CiAgVCBhZGRfZG93biAoY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyByZXR1cm4geCArIHk7IH0KICBUIGFkZF91cCAgIChjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IHJldHVybiB4ICsgeTsgfQogIFQgc3ViX2Rvd24gKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgcmV0dXJuIHggLSB5OyB9CiAgVCBzdWJfdXAgICAoY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyByZXR1cm4geCAtIHk7IH0KICBUIG11bF9kb3duIChjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IHJldHVybiB4ICogeTsgfQogIFQgbXVsX3VwICAgKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgcmV0dXJuIHggKiB5OyB9CiAgVCBkaXZfZG93biAoY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyByZXR1cm4geCAvIHk7IH0KICBUIGRpdl91cCAgIChjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IHJldHVybiB4IC8geTsgfQogIFQgbWVkaWFuICAgKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgcmV0dXJuICh4ICsgeSkgLyAyOyB9CiAgVCBzcXJ0X2Rvd24oY29uc3QgVCYgeCkKICB7IEJPT1NUX05VTUVSSUNfSU5URVJWQUxfdXNpbmdfbWF0aChzcXJ0KTsgcmV0dXJuIHNxcnQoeCk7IH0KICBUIHNxcnRfdXAgIChjb25zdCBUJiB4KQogIHsgQk9PU1RfTlVNRVJJQ19JTlRFUlZBTF91c2luZ19tYXRoKHNxcnQpOyByZXR1cm4gc3FydCh4KTsgfQogIFQgaW50X2Rvd24gKGNvbnN0IFQmIHgpCiAgeyBCT09TVF9OVU1FUklDX0lOVEVSVkFMX3VzaW5nX21hdGgoZmxvb3IpOyByZXR1cm4gZmxvb3IoeCk7IH0KICBUIGludF91cCAgIChjb25zdCBUJiB4KQogIHsgQk9PU1RfTlVNRVJJQ19JTlRFUlZBTF91c2luZ19tYXRoKGNlaWwpOyByZXR1cm4gY2VpbCh4KTsgfQp9OwoKdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgUm91bmRpbmc+CnN0cnVjdCByb3VuZGVkX2FyaXRoX3N0ZDogUm91bmRpbmcgewojIGRlZmluZSBCT09TVF9ETihFWFBSKSB0aGlzLT5kb3dud2FyZCgpOyAgIHJldHVybiB0aGlzLT5mb3JjZV9yb3VuZGluZyhFWFBSKQojIGRlZmluZSBCT09TVF9OUihFWFBSKSB0aGlzLT50b19uZWFyZXN0KCk7IHJldHVybiB0aGlzLT5mb3JjZV9yb3VuZGluZyhFWFBSKQojIGRlZmluZSBCT09TVF9VUChFWFBSKSB0aGlzLT51cHdhcmQoKTsgICAgIHJldHVybiB0aGlzLT5mb3JjZV9yb3VuZGluZyhFWFBSKQogIHZvaWQgaW5pdCgpIHsgfQogIHRlbXBsYXRlPGNsYXNzIFU+IFQgY29udl9kb3duKFUgY29uc3QgJnYpIHsgQk9PU1RfRE4odik7IH0KICB0ZW1wbGF0ZTxjbGFzcyBVPiBUIGNvbnZfdXAgIChVIGNvbnN0ICZ2KSB7IEJPT1NUX1VQKHYpOyB9CiAgVCBhZGRfZG93bihjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IEJPT1NUX0ROKHggKyB5KTsgfQogIFQgc3ViX2Rvd24oY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyBCT09TVF9ETih4IC0geSk7IH0KICBUIG11bF9kb3duKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgQk9PU1RfRE4oeCAqIHkpOyB9CiAgVCBkaXZfZG93bihjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IEJPT1NUX0ROKHggLyB5KTsgfQogIFQgYWRkX3VwICAoY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyBCT09TVF9VUCh4ICsgeSk7IH0KICBUIHN1Yl91cCAgKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgQk9PU1RfVVAoeCAtIHkpOyB9CiAgVCBtdWxfdXAgIChjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IEJPT1NUX1VQKHggKiB5KTsgfQogIFQgZGl2X3VwICAoY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyBCT09TVF9VUCh4IC8geSk7IH0KICBUIG1lZGlhbihjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IEJPT1NUX05SKCh4ICsgeSkgLyAyKTsgfQogIFQgc3FydF9kb3duKGNvbnN0IFQmIHgpCiAgeyBCT09TVF9OVU1FUklDX0lOVEVSVkFMX3VzaW5nX21hdGgoc3FydCk7IEJPT1NUX0ROKHNxcnQoeCkpOyB9CiAgVCBzcXJ0X3VwICAoY29uc3QgVCYgeCkKICB7IEJPT1NUX05VTUVSSUNfSU5URVJWQUxfdXNpbmdfbWF0aChzcXJ0KTsgQk9PU1RfVVAoc3FydCh4KSk7IH0KICBUIGludF9kb3duKGNvbnN0IFQmIHgpIHsgdGhpcy0+ZG93bndhcmQoKTsgcmV0dXJuIHRvX2ludCh4KTsgfQogIFQgaW50X3VwICAoY29uc3QgVCYgeCkgeyB0aGlzLT51cHdhcmQoKTsgICByZXR1cm4gdG9faW50KHgpOyB9CiMgdW5kZWYgQk9PU1RfRE4KIyB1bmRlZiBCT09TVF9OUgojIHVuZGVmIEJPT1NUX1VQCn07CiAgCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFJvdW5kaW5nPgpzdHJ1Y3Qgcm91bmRlZF9hcml0aF9vcHA6IFJvdW5kaW5nIHsKICB2b2lkIGluaXQoKSB7IHRoaXMtPnVwd2FyZCgpOyB9CiMgZGVmaW5lIEJPT1NUX0ROKEVYUFIpIFwKICAgIHRoaXMtPmRvd253YXJkKCk7IFwKICAgIFQgciA9IHRoaXMtPmZvcmNlX3JvdW5kaW5nKEVYUFIpOyBcCiAgICB0aGlzLT51cHdhcmQoKTsgXAogICAgcmV0dXJuIHIKIyBkZWZpbmUgQk9PU1RfTlIoRVhQUikgXAogICAgdGhpcy0+dG9fbmVhcmVzdCgpOyBcCiAgICBUIHIgPSB0aGlzLT5mb3JjZV9yb3VuZGluZyhFWFBSKTsgXAogICAgdGhpcy0+dXB3YXJkKCk7IFwKICAgIHJldHVybiByCiMgZGVmaW5lIEJPT1NUX1VQKEVYUFIpIHJldHVybiB0aGlzLT5mb3JjZV9yb3VuZGluZyhFWFBSKQojIGRlZmluZSBCT09TVF9VUF9ORUcoRVhQUikgcmV0dXJuIC10aGlzLT5mb3JjZV9yb3VuZGluZyhFWFBSKQogIHRlbXBsYXRlPGNsYXNzIFU+IFQgY29udl9kb3duKFUgY29uc3QgJnYpIHsgQk9PU1RfVVBfTkVHKC12KTsgfQogIHRlbXBsYXRlPGNsYXNzIFU+IFQgY29udl91cCAgKFUgY29uc3QgJnYpIHsgQk9PU1RfVVAodik7IH0KICBUIGFkZF9kb3duKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgQk9PU1RfVVBfTkVHKCgteCkgLSB5KTsgfQogIFQgc3ViX2Rvd24oY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyBCT09TVF9VUF9ORUcoeSAtIHgpOyB9CiAgVCBtdWxfZG93bihjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IEJPT1NUX1VQX05FRyh4ICogKC15KSk7IH0KICBUIGRpdl9kb3duKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgQk9PU1RfVVBfTkVHKHggLyAoLXkpKTsgfQogIFQgYWRkX3VwICAoY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyBCT09TVF9VUCh4ICsgeSk7IH0KICBUIHN1Yl91cCAgKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgQk9PU1RfVVAoeCAtIHkpOyB9CiAgVCBtdWxfdXAgIChjb25zdCBUJiB4LCBjb25zdCBUJiB5KSB7IEJPT1NUX1VQKHggKiB5KTsgfQogIFQgZGl2X3VwICAoY29uc3QgVCYgeCwgY29uc3QgVCYgeSkgeyBCT09TVF9VUCh4IC8geSk7IH0KICBUIG1lZGlhbiAgKGNvbnN0IFQmIHgsIGNvbnN0IFQmIHkpIHsgQk9PU1RfTlIoKHggKyB5KSAvIDIpOyB9CiAgVCBzcXJ0X2Rvd24oY29uc3QgVCYgeCkKICB7IEJPT1NUX05VTUVSSUNfSU5URVJWQUxfdXNpbmdfbWF0aChzcXJ0KTsgQk9PU1RfRE4oc3FydCh4KSk7IH0KICBUIHNxcnRfdXAgIChjb25zdCBUJiB4KQogIHsgQk9PU1RfTlVNRVJJQ19JTlRFUlZBTF91c2luZ19tYXRoKHNxcnQpOyBCT09TVF9VUChzcXJ0KHgpKTsgfQogIFQgaW50X2Rvd24oY29uc3QgVCYgeCkgeyByZXR1cm4gLXRvX2ludCgteCk7IH0KICBUIGludF91cCAgKGNvbnN0IFQmIHgpIHsgcmV0dXJuIHRvX2ludCh4KTsgfQojIHVuZGVmIEJPT1NUX0ROCiMgdW5kZWYgQk9PU1RfTlIKIyB1bmRlZiBCT09TVF9VUAojIHVuZGVmIEJPT1NUX1VQX05FRwp9OwoKfSAvLyBuYW1lc3BhY2UgaW50ZXJ2YWxfbGliCn0gLy8gbmFtZXNwYWNlIG51bWVyaWMKfSAvLyBuYW1lc3BhY2UgYm9vc3QKCiNlbmRpZiAvLyBCT09TVF9OVU1FUklDX0lOVEVSVkFMX1JPVU5ERURfQVJJVEhfSFBQCg==