LyoKICogJFhGcmVlODY6IHhjL2xpYi9mb250Y29uZmlnL3NyYy9mY2F0b21pYy5jLHYgMS4xIDIwMDIvMDMvMDMgMDA6MTk6NDMga2VpdGhwIEV4cCAkCiAqCiAqIENvcHlyaWdodCCpIDIwMDIgS2VpdGggUGFja2FyZCwgbWVtYmVyIG9mIFRoZSBYRnJlZTg2IFByb2plY3QsIEluYy4KICoKICogUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgZGlzdHJpYnV0ZSwgYW5kIHNlbGwgdGhpcyBzb2Z0d2FyZSBhbmQgaXRzCiAqIGRvY3VtZW50YXRpb24gZm9yIGFueSBwdXJwb3NlIGlzIGhlcmVieSBncmFudGVkIHdpdGhvdXQgZmVlLCBwcm92aWRlZCB0aGF0CiAqIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFwcGVhciBpbiBhbGwgY29waWVzIGFuZCB0aGF0IGJvdGggdGhhdAogKiBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIGFwcGVhciBpbiBzdXBwb3J0aW5nCiAqIGRvY3VtZW50YXRpb24sIGFuZCB0aGF0IHRoZSBuYW1lIG9mIEtlaXRoIFBhY2thcmQgbm90IGJlIHVzZWQgaW4KICogYWR2ZXJ0aXNpbmcgb3IgcHVibGljaXR5IHBlcnRhaW5pbmcgdG8gZGlzdHJpYnV0aW9uIG9mIHRoZSBzb2Z0d2FyZSB3aXRob3V0CiAqIHNwZWNpZmljLCB3cml0dGVuIHByaW9yIHBlcm1pc3Npb24uICBLZWl0aCBQYWNrYXJkIG1ha2VzIG5vCiAqIHJlcHJlc2VudGF0aW9ucyBhYm91dCB0aGUgc3VpdGFiaWxpdHkgb2YgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UuICBJdAogKiBpcyBwcm92aWRlZCAiYXMgaXMiIHdpdGhvdXQgZXhwcmVzcyBvciBpbXBsaWVkIHdhcnJhbnR5LgogKgogKiBLRUlUSCBQQUNLQVJEIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIIFJFR0FSRCBUTyBUSElTIFNPRlRXQVJFLAogKiBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MsIElOIE5PCiAqIEVWRU5UIFNIQUxMIEtFSVRIIFBBQ0tBUkQgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgSU5ESVJFQ1QgT1IKICogQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST00gTE9TUyBPRiBVU0UsCiAqIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1IgT1RIRVIKICogVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUgogKiBQRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLgogKi8KCi8qCiAqIGZjYXRvbWljLmMKICoKICogTG9jayBjYWNoZSBhbmQgY29uZmlndXJhdGlvbiBmaWxlcyBmb3IgYXRvbWljIHVwZGF0ZQogKgogKiBVc2VzIG9ubHkgcmVndWxhciBmaWxlc3lzdGVtIGNhbGxzIHNvIGl0IHNob3VsZAogKiB3b3JrIGV2ZW4gaW4gdGhlIGFic2Vuc2Ugb2YgZnVuY3Rpb25pbmcgZmlsZSBsb2NraW5nCiAqCiAqICBGb3VyIGZpbGVzOgogKglmaWxlCSAgICAtIHRoZSBkYXRhIGZpbGUgYWNjZXNzZWQgYnkgb3RoZXIgYXBwcy4KICoJbmV3CSAgICAtIGEgbmV3IHZlcnNpb24gb2YgdGhlIGRhdGEgZmlsZSB3aGlsZSBpdCdzIGJlaW5nIHdyaXR0ZW4KICoJbGNrCSAgICAtIHRoZSBsb2NrIGZpbGUKICoJdG1wCSAgICAtIGEgdGVtcG9yYXJ5IGZpbGUgbWFkZSB1bmlxdWUgd2l0aCBta3N0ZW1wCiAqCiAqICBIZXJlJ3MgaG93IGl0IHdvcmtzOgogKglDcmVhdGUgJ3RtcCcgYW5kIHN0b3JlIG91ciBQSUQgaW4gaXQKICoJQXR0ZW1wdCB0byBsaW5rIGl0IHRvICdsY2snCiAqCVVubGluayAndG1wJwogKglJZiB0aGUgbGluayBzdWNjZWVkZWQsIHRoZSBsb2NrIGlzIGhlbGQKICovCgojaW5jbHVkZSAiZmNpbnQuaCIKI2luY2x1ZGUgPHN5cy90eXBlcy5oPgojaW5jbHVkZSA8c3lzL3N0YXQuaD4KI2luY2x1ZGUgPGZjbnRsLmg+CiNpbmNsdWRlIDx1bmlzdGQuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8dGltZS5oPgoKI2RlZmluZSBORVdfTkFNRQkiLk5FVyIKI2RlZmluZSBMQ0tfTkFNRQkiLkxDSyIKI2RlZmluZSBUTVBfTkFNRQkiLlRNUC1YWFhYWFgiCgpGY0F0b21pYyAqCkZjQXRvbWljQ3JlYXRlIChjb25zdCBGY0NoYXI4ICAgKmZpbGUpCnsKICAgIGludAkgICAgZmlsZV9sZW4gPSBzdHJsZW4gKChjaGFyICopIGZpbGUpOwogICAgaW50CSAgICBuZXdfbGVuID0gZmlsZV9sZW4gKyBzaXplb2YgKE5FV19OQU1FKTsKICAgIGludAkgICAgbGNrX2xlbiA9IGZpbGVfbGVuICsgc2l6ZW9mIChMQ0tfTkFNRSk7CiAgICBpbnQJICAgIHRtcF9sZW4gPSBmaWxlX2xlbiArIHNpemVvZiAoVE1QX05BTUUpOwogICAgaW50CSAgICB0b3RhbF9sZW4gPSAoc2l6ZW9mIChGY0F0b21pYykgKwoJCQkgZmlsZV9sZW4gKyAxICsKCQkJIG5ld19sZW4gKyAxICsKCQkJIGxja19sZW4gKyAxICsKCQkJIHRtcF9sZW4gKyAxKTsKICAgIEZjQXRvbWljCSphdG9taWMgPSBtYWxsb2MgKHRvdGFsX2xlbik7CiAgICBpZiAoIWF0b21pYykKCXJldHVybiAwOwogICAgCiAgICBhdG9taWMtPmZpbGUgPSAoRmNDaGFyOCAqKSAoYXRvbWljICsgMSk7CiAgICBzdHJjcHkgKChjaGFyICopIGF0b21pYy0+ZmlsZSwgKGNoYXIgKikgZmlsZSk7CgogICAgYXRvbWljLT5uZXcgPSBhdG9taWMtPmZpbGUgKyBmaWxlX2xlbiArIDE7CiAgICBzdHJjcHkgKChjaGFyICopIGF0b21pYy0+bmV3LCAoY2hhciAqKSBmaWxlKTsKICAgIHN0cmNhdCAoKGNoYXIgKikgYXRvbWljLT5uZXcsIE5FV19OQU1FKTsKCiAgICBhdG9taWMtPmxjayA9IGF0b21pYy0+bmV3ICsgbmV3X2xlbiArIDE7CiAgICBzdHJjcHkgKChjaGFyICopIGF0b21pYy0+bGNrLCAoY2hhciAqKSBmaWxlKTsKICAgIHN0cmNhdCAoKGNoYXIgKikgYXRvbWljLT5sY2ssIExDS19OQU1FKTsKCiAgICBhdG9taWMtPnRtcCA9IGF0b21pYy0+bGNrICsgbGNrX2xlbiArIDE7CgogICAgcmV0dXJuIGF0b21pYzsKfQoKRmNCb29sCkZjQXRvbWljTG9jayAoRmNBdG9taWMgKmF0b21pYykKewogICAgaW50CQlmZCA9IC0xOwogICAgRklMRQkqZiA9IDA7CiAgICBpbnQJCXJldDsKICAgIHN0cnVjdCBzdGF0CWxja19zdGF0OwoKICAgIHN0cmNweSAoKGNoYXIgKikgYXRvbWljLT50bXAsIChjaGFyICopIGF0b21pYy0+ZmlsZSk7CiAgICBzdHJjYXQgKChjaGFyICopIGF0b21pYy0+dG1wLCBUTVBfTkFNRSk7CiAgICBmZCA9IG1rc3RlbXAgKChjaGFyICopIGF0b21pYy0+dG1wKTsKICAgIGlmIChmZCA8IDApCglyZXR1cm4gRmNGYWxzZTsKICAgIGYgPSBmZG9wZW4gKGZkLCAidyIpOwogICAgaWYgKCFmKQogICAgewogICAgCWNsb3NlIChmZCk7Cgl1bmxpbmsgKChjaGFyICopIGF0b21pYy0+dG1wKTsKCXJldHVybiBGY0ZhbHNlOwogICAgfQogICAgcmV0ID0gZnByaW50ZiAoZiwgIiVsZFxuIiwgKGxvbmcpZ2V0cGlkKCkpOwogICAgaWYgKHJldCA8PSAwKQogICAgewoJZmNsb3NlIChmKTsKCXVubGluayAoKGNoYXIgKikgYXRvbWljLT50bXApOwoJcmV0dXJuIEZjRmFsc2U7CiAgICB9CiAgICBpZiAoZmNsb3NlIChmKSA9PSBFT0YpCiAgICB7Cgl1bmxpbmsgKChjaGFyICopIGF0b21pYy0+dG1wKTsKCXJldHVybiBGY0ZhbHNlOwogICAgfQogICAgcmV0ID0gbGluayAoKGNoYXIgKikgYXRvbWljLT50bXAsIChjaGFyICopIGF0b21pYy0+bGNrKTsKICAgICh2b2lkKSB1bmxpbmsgKChjaGFyICopIGF0b21pYy0+dG1wKTsKICAgIGlmIChyZXQgPCAwKQogICAgewoJLyoKCSAqIElmIHRoZSBmaWxlIGlzIGFyb3VuZCBhbmQgb2xkICg+IDEwIG1pbnV0ZXMpLAoJICogYXNzdW1lIHRoZSBsb2NrIGlzIHN0YWxlLiAgVGhpcyBhc3N1bWVzIHRoYXQgYW55CgkgKiBtYWNoaW5lcyBzaGFyaW5nIHRoZSBzYW1lIGZpbGVzeXN0ZW0gd2lsbCBoYXZlIGNsb2NrcwoJICogcmVhc29uYWJseSBjbG9zZSB0byBlYWNoIG90aGVyLgoJICovCglpZiAoc3RhdCAoKGNoYXIgKikgYXRvbWljLT5sY2ssICZsY2tfc3RhdCkgPj0gMCkKCXsKCSAgICB0aW1lX3QgIG5vdyA9IHRpbWUgKDApOwoJICAgIGlmICgobG9uZyBpbnQpIChub3cgLSBsY2tfc3RhdC5zdF9tdGltZSkgPiAxMCAqIDYwKQoJICAgIHsKCQlpZiAodW5saW5rICgoY2hhciAqKSBhdG9taWMtPmxjaykgPT0gMCkKCQkgICAgcmV0dXJuIEZjQXRvbWljTG9jayAoYXRvbWljKTsKCSAgICB9Cgl9CglyZXR1cm4gRmNGYWxzZTsKICAgIH0KICAgICh2b2lkKSB1bmxpbmsgKChjaGFyICopIGF0b21pYy0+bmV3KTsKICAgIHJldHVybiBGY1RydWU7Cn0KCkZjQ2hhcjggKgpGY0F0b21pY05ld0ZpbGUgKEZjQXRvbWljICphdG9taWMpCnsKICAgIHJldHVybiBhdG9taWMtPm5ldzsKfQoKRmNDaGFyOCAqCkZjQXRvbWljT3JpZ0ZpbGUgKEZjQXRvbWljICphdG9taWMpCnsKICAgIHJldHVybiBhdG9taWMtPmZpbGU7Cn0KCkZjQm9vbApGY0F0b21pY1JlcGxhY2VPcmlnIChGY0F0b21pYyAqYXRvbWljKQp7CiAgICBpZiAocmVuYW1lICgoY2hhciAqKSBhdG9taWMtPm5ldywgKGNoYXIgKikgYXRvbWljLT5maWxlKSA8IDApCglyZXR1cm4gRmNGYWxzZTsKICAgIHJldHVybiBGY1RydWU7Cn0KCnZvaWQKRmNBdG9taWNEZWxldGVOZXcgKEZjQXRvbWljICphdG9taWMpCnsKICAgIHVubGluayAoKGNoYXIgKikgYXRvbWljLT5uZXcpOwp9Cgp2b2lkCkZjQXRvbWljVW5sb2NrIChGY0F0b21pYyAqYXRvbWljKQp7CiAgICB1bmxpbmsgKChjaGFyICopIGF0b21pYy0+bGNrKTsKfQoKdm9pZApGY0F0b21pY0Rlc3Ryb3kgKEZjQXRvbWljICphdG9taWMpCnsKICAgIGZyZWUgKGF0b21pYyk7Cn0K