LyoKICogJFhGcmVlODY6IHhjL2xpYi9mb250Y29uZmlnL3NyYy9mY2xpc3QuYyx2IDEuNyAyMDAyLzA2LzE5IDIwOjA4OjIyIGtlaXRocCBFeHAgJAogKgogKiBDb3B5cmlnaHQgqSAyMDAwIEtlaXRoIFBhY2thcmQsIG1lbWJlciBvZiBUaGUgWEZyZWU4NiBQcm9qZWN0LCBJbmMuCiAqCiAqIFBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGRpc3RyaWJ1dGUsIGFuZCBzZWxsIHRoaXMgc29mdHdhcmUgYW5kIGl0cwogKiBkb2N1bWVudGF0aW9uIGZvciBhbnkgcHVycG9zZSBpcyBoZXJlYnkgZ3JhbnRlZCB3aXRob3V0IGZlZSwgcHJvdmlkZWQgdGhhdAogKiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhcHBlYXIgaW4gYWxsIGNvcGllcyBhbmQgdGhhdCBib3RoIHRoYXQKICogY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBhcHBlYXIgaW4gc3VwcG9ydGluZwogKiBkb2N1bWVudGF0aW9uLCBhbmQgdGhhdCB0aGUgbmFtZSBvZiBLZWl0aCBQYWNrYXJkIG5vdCBiZSB1c2VkIGluCiAqIGFkdmVydGlzaW5nIG9yIHB1YmxpY2l0eSBwZXJ0YWluaW5nIHRvIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc29mdHdhcmUgd2l0aG91dAogKiBzcGVjaWZpYywgd3JpdHRlbiBwcmlvciBwZXJtaXNzaW9uLiAgS2VpdGggUGFja2FyZCBtYWtlcyBubwogKiByZXByZXNlbnRhdGlvbnMgYWJvdXQgdGhlIHN1aXRhYmlsaXR5IG9mIHRoaXMgc29mdHdhcmUgZm9yIGFueSBwdXJwb3NlLiAgSXQKICogaXMgcHJvdmlkZWQgImFzIGlzIiB3aXRob3V0IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4KICoKICogS0VJVEggUEFDS0FSRCBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSCBSRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSwKICogSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTLCBJTiBOTwogKiBFVkVOVCBTSEFMTCBLRUlUSCBQQUNLQVJEIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIElORElSRUNUIE9SCiAqIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NIExPU1MgT0YgVVNFLAogKiBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SIE9USEVSCiAqIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1IKICogUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS4KICovCgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlICJmY2ludC5oIgoKRmNPYmplY3RTZXQgKgpGY09iamVjdFNldENyZWF0ZSAodm9pZCkKewogICAgRmNPYmplY3RTZXQgICAgKm9zOwoKICAgIG9zID0gKEZjT2JqZWN0U2V0ICopIG1hbGxvYyAoc2l6ZW9mIChGY09iamVjdFNldCkpOwogICAgaWYgKCFvcykKCXJldHVybiAwOwogICAgRmNNZW1BbGxvYyAoRkNfTUVNX09CSkVDVFNFVCwgc2l6ZW9mIChGY09iamVjdFNldCkpOwogICAgb3MtPm5vYmplY3QgPSAwOwogICAgb3MtPnNvYmplY3QgPSAwOwogICAgb3MtPm9iamVjdHMgPSAwOwogICAgcmV0dXJuIG9zOwp9CgpGY0Jvb2wKRmNPYmplY3RTZXRBZGQgKEZjT2JqZWN0U2V0ICpvcywgY29uc3QgY2hhciAqb2JqZWN0KQp7CiAgICBpbnQJCXM7CiAgICBjb25zdCBjaGFyCSoqb2JqZWN0czsKICAgIGludAkJaGlnaCwgbG93LCBtaWQsIGM7CiAgICAKICAgIGlmIChvcy0+bm9iamVjdCA9PSBvcy0+c29iamVjdCkKICAgIHsKCXMgPSBvcy0+c29iamVjdCArIDQ7CglpZiAob3MtPm9iamVjdHMpCgkgICAgb2JqZWN0cyA9IChjb25zdCBjaGFyICoqKSByZWFsbG9jICgodm9pZCAqKSBvcy0+b2JqZWN0cywKCQkJCQkgICAgICAgcyAqIHNpemVvZiAoY29uc3QgY2hhciAqKSk7CgllbHNlCgkgICAgb2JqZWN0cyA9IChjb25zdCBjaGFyICoqKSBtYWxsb2MgKHMgKiBzaXplb2YgKGNvbnN0IGNoYXIgKikpOwoJaWYgKCFvYmplY3RzKQoJICAgIHJldHVybiBGY0ZhbHNlOwoJaWYgKG9zLT5zb2JqZWN0KQoJICAgIEZjTWVtRnJlZSAoRkNfTUVNX09CSkVDVFBUUiwgb3MtPnNvYmplY3QgKiBzaXplb2YgKGNvbnN0IGNoYXIgKikpOwoJRmNNZW1BbGxvYyAoRkNfTUVNX09CSkVDVFBUUiwgcyAqIHNpemVvZiAoY29uc3QgY2hhciAqKSk7Cglvcy0+b2JqZWN0cyA9IG9iamVjdHM7Cglvcy0+c29iamVjdCA9IHM7CiAgICB9CiAgICBoaWdoID0gb3MtPm5vYmplY3QgLSAxOwogICAgbG93ID0gMDsKICAgIG1pZCA9IDA7CiAgICBjID0gMTsKICAgIHdoaWxlIChsb3cgPD0gaGlnaCkKICAgIHsKCW1pZCA9IChsb3cgKyBoaWdoKSA+PiAxOwoJYyA9IHN0cmNtcCAob3MtPm9iamVjdHNbbWlkXSwgb2JqZWN0KTsKCWlmIChjID09IDApCgkgICAgcmV0dXJuIEZjVHJ1ZTsKCWlmIChjIDwgMCkKCSAgICBsb3cgPSBtaWQgKyAxOwoJZWxzZQoJICAgIGhpZ2ggPSBtaWQgLSAxOwogICAgfQogICAgaWYgKGMgPCAwKQoJbWlkKys7CiAgICBtZW1tb3ZlIChvcy0+b2JqZWN0cyArIG1pZCArIDEsIG9zLT5vYmplY3RzICsgbWlkLCAKCSAgICAgKG9zLT5ub2JqZWN0IC0gbWlkKSAqIHNpemVvZiAoY29uc3QgY2hhciAqKSk7CiAgICBvcy0+b2JqZWN0c1ttaWRdID0gb2JqZWN0OwogICAgb3MtPm5vYmplY3QrKzsKICAgIHJldHVybiBGY1RydWU7Cn0KCnZvaWQKRmNPYmplY3RTZXREZXN0cm95IChGY09iamVjdFNldCAqb3MpCnsKICAgIGlmIChvcy0+b2JqZWN0cykKICAgIHsKCUZjTWVtRnJlZSAoRkNfTUVNX09CSkVDVFBUUiwgb3MtPnNvYmplY3QgKiBzaXplb2YgKGNvbnN0IGNoYXIgKikpOwoJZnJlZSAoKHZvaWQgKikgb3MtPm9iamVjdHMpOwogICAgfQogICAgRmNNZW1GcmVlIChGQ19NRU1fT0JKRUNUU0VULCBzaXplb2YgKEZjT2JqZWN0U2V0KSk7CiAgICBmcmVlIChvcyk7Cn0KCkZjT2JqZWN0U2V0ICoKRmNPYmplY3RTZXRWYUJ1aWxkIChjb25zdCBjaGFyICpmaXJzdCwgdmFfbGlzdCB2YSkKewogICAgRmNPYmplY3RTZXQgICAgKnJldDsKCiAgICBGY09iamVjdFNldFZhcEJ1aWxkIChyZXQsIGZpcnN0LCB2YSk7CiAgICByZXR1cm4gcmV0Owp9CgpGY09iamVjdFNldCAqCkZjT2JqZWN0U2V0QnVpbGQgKGNvbnN0IGNoYXIgKmZpcnN0LCAuLi4pCnsKICAgIHZhX2xpc3QJICAgIHZhOwogICAgRmNPYmplY3RTZXQgICAgKm9zOwoKICAgIHZhX3N0YXJ0ICh2YSwgZmlyc3QpOwogICAgRmNPYmplY3RTZXRWYXBCdWlsZCAob3MsIGZpcnN0LCB2YSk7CiAgICB2YV9lbmQgKHZhKTsKICAgIHJldHVybiBvczsKfQoKc3RhdGljIEZjQm9vbApGY0xpc3RWYWx1ZUxpc3RNYXRjaEFueSAoRmNWYWx1ZUxpc3QgKnYxb3JpZywKCQkJIEZjVmFsdWVMaXN0ICp2Mm9yaWcpCnsKICAgIEZjVmFsdWVMaXN0CSAgICAqdjEsICp2MjsKCiAgICBmb3IgKHYxID0gdjFvcmlnOyB2MTsgdjEgPSB2MS0+bmV4dCkKCWZvciAodjIgPSB2Mm9yaWc7IHYyOyB2MiA9IHYyLT5uZXh0KQoJICAgIGlmIChGY0NvbmZpZ0NvbXBhcmVWYWx1ZSAodjItPnZhbHVlLCBGY09wQ29udGFpbnMsIHYxLT52YWx1ZSkpCgkJcmV0dXJuIEZjVHJ1ZTsKICAgIHJldHVybiBGY0ZhbHNlOwp9CgpzdGF0aWMgRmNCb29sCkZjTGlzdFZhbHVlTGlzdEVxdWFsIChGY1ZhbHVlTGlzdCAgICp2MW9yaWcsCgkJICAgICAgRmNWYWx1ZUxpc3QgICAqdjJvcmlnKQp7CiAgICBGY1ZhbHVlTGlzdAkgICAgKnYxLCAqdjI7CgogICAgZm9yICh2MSA9IHYxb3JpZzsgdjE7IHYxID0gdjEtPm5leHQpCiAgICB7Cglmb3IgKHYyID0gdjJvcmlnOyB2MjsgdjIgPSB2Mi0+bmV4dCkKCSAgICBpZiAoRmNDb25maWdDb21wYXJlVmFsdWUgKHYxLT52YWx1ZSwgRmNPcEVxdWFsLCB2Mi0+dmFsdWUpKQoJCWJyZWFrOwoJaWYgKCF2MikKCSAgICByZXR1cm4gRmNGYWxzZTsKICAgIH0KICAgIGZvciAodjIgPSB2Mm9yaWc7IHYyOyB2MiA9IHYyLT5uZXh0KQogICAgewoJZm9yICh2MSA9IHYxb3JpZzsgdjE7IHYxID0gdjEtPm5leHQpCgkgICAgaWYgKEZjQ29uZmlnQ29tcGFyZVZhbHVlICh2MS0+dmFsdWUsIEZjT3BFcXVhbCwgdjItPnZhbHVlKSkKCQlicmVhazsKCWlmICghdjEpCgkgICAgcmV0dXJuIEZjRmFsc2U7CiAgICB9CiAgICByZXR1cm4gRmNUcnVlOwp9CgpzdGF0aWMgRmNCb29sCkZjTGlzdFBhdHRlcm5FcXVhbCAoRmNQYXR0ZXJuCSpwMSwKCQkgICAgRmNQYXR0ZXJuCSpwMiwKCQkgICAgRmNPYmplY3RTZXQJKm9zKQp7CiAgICBpbnQJCSAgICBpOwogICAgRmNQYXR0ZXJuRWx0ICAgICplMSwgKmUyOwoKICAgIGZvciAoaSA9IDA7IGkgPCBvcy0+bm9iamVjdDsgaSsrKQogICAgewoJZTEgPSBGY1BhdHRlcm5GaW5kRWx0IChwMSwgb3MtPm9iamVjdHNbaV0pOwoJZTIgPSBGY1BhdHRlcm5GaW5kRWx0IChwMiwgb3MtPm9iamVjdHNbaV0pOwoJaWYgKCFlMSAmJiAhZTIpCgkgICAgcmV0dXJuIEZjVHJ1ZTsKCWlmICghZTEgfHwgIWUyKQoJICAgIHJldHVybiBGY0ZhbHNlOwoJaWYgKCFGY0xpc3RWYWx1ZUxpc3RFcXVhbCAoZTEtPnZhbHVlcywgZTItPnZhbHVlcykpCgkgICAgcmV0dXJuIEZjRmFsc2U7CiAgICB9CiAgICByZXR1cm4gRmNUcnVlOwp9CgovKgogKiBGY1RydWUgaWZmIGFsbCBvYmplY3RzIGluICJwIiBtYXRjaCAiZm9udCIKICovCgpzdGF0aWMgRmNCb29sCkZjTGlzdFBhdHRlcm5NYXRjaEFueSAoRmNQYXR0ZXJuICpwLAoJCSAgICAgICBGY1BhdHRlcm4gKmZvbnQpCnsKICAgIGludAkJICAgIGk7CiAgICBGY1BhdHRlcm5FbHQgICAqZTsKCiAgICBmb3IgKGkgPSAwOyBpIDwgcC0+bnVtOyBpKyspCiAgICB7CgllID0gRmNQYXR0ZXJuRmluZEVsdCAoZm9udCwgcC0+ZWx0c1tpXS5vYmplY3QpOwoJaWYgKCFlKQoJICAgIHJldHVybiBGY0ZhbHNlOwoJaWYgKCFGY0xpc3RWYWx1ZUxpc3RNYXRjaEFueSAocC0+ZWx0c1tpXS52YWx1ZXMsIGUtPnZhbHVlcykpCgkgICAgcmV0dXJuIEZjRmFsc2U7CiAgICB9CiAgICByZXR1cm4gRmNUcnVlOwp9CgpzdGF0aWMgRmNDaGFyMzIKRmNMaXN0U3RyaW5nSGFzaCAoY29uc3QgRmNDaGFyOAkqcykKewogICAgRmNDaGFyMzIJaCA9IDA7CiAgICBGY0NoYXI4CWM7CgogICAgd2hpbGUgKChjID0gKnMrKykpCiAgICB7CgljID0gRmNUb0xvd2VyIChjKTsKCWggPSAoKGggPDwgMykgXiAoaCA+PiAzKSkgXiBjOwogICAgfQogICAgcmV0dXJuIGg7Cn0KCnN0YXRpYyBGY0NoYXIzMgpGY0xpc3RNYXRyaXhIYXNoIChjb25zdCBGY01hdHJpeCAqbSkKewogICAgaW50CSAgICB4eCA9IChpbnQpIChtLT54eCAqIDEwMCksIAoJICAgIHh5ID0gKGludCkgKG0tPnh5ICogMTAwKSwgCgkgICAgeXggPSAoaW50KSAobS0+eXggKiAxMDApLAoJICAgIHl5ID0gKGludCkgKG0tPnl5ICogMTAwKTsKCiAgICByZXR1cm4gKChGY0NoYXIzMikgeHgpIF4gKChGY0NoYXIzMikgeHkpIF4gKChGY0NoYXIzMikgeXgpIF4gKChGY0NoYXIzMikgeXkpOwp9CgpzdGF0aWMgRmNDaGFyMzIKRmNMaXN0VmFsdWVIYXNoIChGY1ZhbHVlICAgIHYpCnsKICAgIHN3aXRjaCAodi50eXBlKSB7CiAgICBjYXNlIEZjVHlwZVZvaWQ6CglyZXR1cm4gMDsKICAgIGNhc2UgRmNUeXBlSW50ZWdlcjoKCXJldHVybiAoRmNDaGFyMzIpIHYudS5pOwogICAgY2FzZSBGY1R5cGVEb3VibGU6CglyZXR1cm4gKEZjQ2hhcjMyKSAoaW50KSB2LnUuZDsKICAgIGNhc2UgRmNUeXBlU3RyaW5nOgoJcmV0dXJuIEZjTGlzdFN0cmluZ0hhc2ggKHYudS5zKTsKICAgIGNhc2UgRmNUeXBlQm9vbDoKCXJldHVybiAoRmNDaGFyMzIpIHYudS5iOwogICAgY2FzZSBGY1R5cGVNYXRyaXg6CglyZXR1cm4gRmNMaXN0TWF0cml4SGFzaCAodi51Lm0pOwogICAgY2FzZSBGY1R5cGVDaGFyU2V0OgoJcmV0dXJuIEZjQ2hhclNldENvdW50ICh2LnUuYyk7CiAgICBjYXNlIEZjVHlwZUZURmFjZToKCXJldHVybiAoRmNDaGFyMzIpIHYudS5mOwogICAgY2FzZSBGY1R5cGVQYXR0ZXJuOgoJcmV0dXJuIChGY0NoYXIzMikgdi51LnAtPm51bTsKICAgIH0KICAgIHJldHVybiAwOwp9CgpzdGF0aWMgRmNDaGFyMzIKRmNMaXN0VmFsdWVMaXN0SGFzaCAoRmNWYWx1ZUxpc3QgICAgKmxpc3QpCnsKICAgIEZjQ2hhcjMyCWggPSAwOwogICAgCiAgICB3aGlsZSAobGlzdCkKICAgIHsKCWggPSBoIF4gRmNMaXN0VmFsdWVIYXNoIChsaXN0LT52YWx1ZSk7CglsaXN0ID0gbGlzdC0+bmV4dDsKICAgIH0KICAgIHJldHVybiBoOwp9CgpzdGF0aWMgRmNDaGFyMzIKRmNMaXN0UGF0dGVybkhhc2ggKEZjUGF0dGVybgkqZm9udCwKCQkgICBGY09iamVjdFNldAkqb3MpCnsKICAgIGludAkJICAgIG47CiAgICBGY1BhdHRlcm5FbHQgICAgKmU7CiAgICBGY0NoYXIzMgkgICAgaCA9IDA7CgogICAgZm9yIChuID0gMDsgbiA8IG9zLT5ub2JqZWN0OyBuKyspCiAgICB7CgllID0gRmNQYXR0ZXJuRmluZEVsdCAoZm9udCwgb3MtPm9iamVjdHNbbl0pOwoJaWYgKGUpCgkgICAgaCA9IGggXiBGY0xpc3RWYWx1ZUxpc3RIYXNoIChlLT52YWx1ZXMpOwogICAgfQogICAgcmV0dXJuIGg7Cn0KCnR5cGVkZWYgc3RydWN0IF9GY0xpc3RCdWNrZXQgewogICAgc3RydWN0IF9GY0xpc3RCdWNrZXQgICAgKm5leHQ7CiAgICBGY0NoYXIzMgkJICAgIGhhc2g7CiAgICBGY1BhdHRlcm4JCSAgICAqcGF0dGVybjsKfSBGY0xpc3RCdWNrZXQ7CgojZGVmaW5lIEZDX0xJU1RfSEFTSF9TSVpFICAgNDA5OQoKdHlwZWRlZiBzdHJ1Y3QgX0ZjTGlzdEhhc2hUYWJsZSB7CiAgICBpbnQJCSAgICBlbnRyaWVzOwogICAgRmNMaXN0QnVja2V0ICAgICpidWNrZXRzW0ZDX0xJU1RfSEFTSF9TSVpFXTsKfSBGY0xpc3RIYXNoVGFibGU7CiAgICAKc3RhdGljIHZvaWQKRmNMaXN0SGFzaFRhYmxlSW5pdCAoRmNMaXN0SGFzaFRhYmxlICp0YWJsZSkKewogICAgdGFibGUtPmVudHJpZXMgPSAwOwogICAgbWVtc2V0ICh0YWJsZS0+YnVja2V0cywgJ1wwJywgc2l6ZW9mICh0YWJsZS0+YnVja2V0cykpOwp9CgpzdGF0aWMgdm9pZApGY0xpc3RIYXNoVGFibGVDbGVhbnVwIChGY0xpc3RIYXNoVGFibGUgKnRhYmxlKQp7CiAgICBpbnQJaTsKICAgIEZjTGlzdEJ1Y2tldCAgICAqYnVja2V0LCAqbmV4dDsKCiAgICBmb3IgKGkgPSAwOyBpIDwgRkNfTElTVF9IQVNIX1NJWkU7IGkrKykKICAgIHsKCWZvciAoYnVja2V0ID0gdGFibGUtPmJ1Y2tldHNbaV07IGJ1Y2tldDsgYnVja2V0ID0gbmV4dCkKCXsKCSAgICBuZXh0ID0gYnVja2V0LT5uZXh0OwoJICAgIEZjUGF0dGVybkRlc3Ryb3kgKGJ1Y2tldC0+cGF0dGVybik7CgkgICAgRmNNZW1GcmVlIChGQ19NRU1fTElTVEJVQ0ssIHNpemVvZiAoRmNMaXN0QnVja2V0KSk7CgkgICAgZnJlZSAoYnVja2V0KTsKCX0KCXRhYmxlLT5idWNrZXRzW2ldID0gMDsKICAgIH0KICAgIHRhYmxlLT5lbnRyaWVzID0gMDsKfQoKc3RhdGljIEZjQm9vbApGY0xpc3RBcHBlbmQgKEZjTGlzdEhhc2hUYWJsZQkqdGFibGUsCgkgICAgICBGY1BhdHRlcm4JCSpmb250LAoJICAgICAgRmNPYmplY3RTZXQJKm9zKQp7CiAgICBpbnQJCSAgICBvOwogICAgRmNQYXR0ZXJuRWx0ICAgICplOwogICAgRmNWYWx1ZUxpc3QJICAgICp2OwogICAgRmNDaGFyMzIJICAgIGhhc2g7CiAgICBGY0xpc3RCdWNrZXQgICAgKipwcmV2LCAqYnVja2V0OwoKICAgIGhhc2ggPSBGY0xpc3RQYXR0ZXJuSGFzaCAoZm9udCwgb3MpOwogICAgZm9yIChwcmV2ID0gJnRhYmxlLT5idWNrZXRzW2hhc2ggJSBGQ19MSVNUX0hBU0hfU0laRV07CgkgKGJ1Y2tldCA9ICpwcmV2KTsgcHJldiA9ICYoYnVja2V0LT5uZXh0KSkKICAgIHsKCWlmIChidWNrZXQtPmhhc2ggPT0gaGFzaCAmJiAKCSAgICBGY0xpc3RQYXR0ZXJuRXF1YWwgKGJ1Y2tldC0+cGF0dGVybiwgZm9udCwgb3MpKQoJICAgIHJldHVybiBGY1RydWU7CiAgICB9CiAgICBidWNrZXQgPSAoRmNMaXN0QnVja2V0ICopIG1hbGxvYyAoc2l6ZW9mIChGY0xpc3RCdWNrZXQpKTsKICAgIGlmICghYnVja2V0KQoJZ290byBiYWlsMDsKICAgIEZjTWVtQWxsb2MgKEZDX01FTV9MSVNUQlVDSywgc2l6ZW9mIChGY0xpc3RCdWNrZXQpKTsKICAgIGJ1Y2tldC0+bmV4dCA9IDA7CiAgICBidWNrZXQtPmhhc2ggPSBoYXNoOwogICAgYnVja2V0LT5wYXR0ZXJuID0gRmNQYXR0ZXJuQ3JlYXRlICgpOwogICAgaWYgKCFidWNrZXQtPnBhdHRlcm4pCglnb3RvIGJhaWwxOwogICAgCiAgICBmb3IgKG8gPSAwOyBvIDwgb3MtPm5vYmplY3Q7IG8rKykKICAgIHsKCWUgPSBGY1BhdHRlcm5GaW5kRWx0IChmb250LCBvcy0+b2JqZWN0c1tvXSk7CglpZiAoZSkKCXsKCSAgICBmb3IgKHYgPSBlLT52YWx1ZXM7IHY7IHYgPSB2LT5uZXh0KQoJICAgIHsKCQlpZiAoIUZjUGF0dGVybkFkZCAoYnVja2V0LT5wYXR0ZXJuLCAKCQkJCSAgIG9zLT5vYmplY3RzW29dLCAKCQkJCSAgIHYtPnZhbHVlLCBGY1RydWUpKQoJCSAgICBnb3RvIGJhaWwyOwoJICAgIH0KCX0KICAgIH0KICAgICpwcmV2ID0gYnVja2V0OwogICAgKyt0YWJsZS0+ZW50cmllczsKCiAgICByZXR1cm4gRmNUcnVlOwogICAgCmJhaWwyOgogICAgRmNQYXR0ZXJuRGVzdHJveSAoYnVja2V0LT5wYXR0ZXJuKTsKYmFpbDE6CiAgICBGY01lbUZyZWUgKEZDX01FTV9MSVNUQlVDSywgc2l6ZW9mIChGY0xpc3RCdWNrZXQpKTsKICAgIGZyZWUgKGJ1Y2tldCk7CmJhaWwwOgogICAgcmV0dXJuIEZjRmFsc2U7Cn0KCkZjRm9udFNldCAqCkZjRm9udFNldExpc3QgKEZjQ29uZmlnCSAgICAqY29uZmlnLAoJICAgICAgIEZjRm9udFNldCAgICAqKnNldHMsCgkgICAgICAgaW50CSAgICBuc2V0cywKCSAgICAgICBGY1BhdHRlcm4gICAgKnAsCgkgICAgICAgRmNPYmplY3RTZXQgICpvcykKewogICAgRmNGb250U2V0CSAgICAqcmV0OwogICAgRmNGb250U2V0CSAgICAqczsKICAgIGludAkJICAgIGY7CiAgICBpbnQJCSAgICBzZXQ7CiAgICBGY0xpc3RIYXNoVGFibGUgdGFibGU7CiAgICBpbnQJCSAgICBpOwogICAgRmNMaXN0QnVja2V0ICAgICpidWNrZXQ7CgogICAgaWYgKCFjb25maWcpCiAgICB7CglpZiAoIUZjSW5pdEJyaW5nVXB0b0RhdGUgKCkpCgkgICAgZ290byBiYWlsMDsKCgljb25maWcgPSBGY0NvbmZpZ0dldEN1cnJlbnQgKCk7CglpZiAoIWNvbmZpZykKCSAgICBnb3RvIGJhaWwwOwogICAgfQogICAgRmNMaXN0SGFzaFRhYmxlSW5pdCAoJnRhYmxlKTsKICAgIC8qCiAgICAgKiBXYWxrIGFsbCBhdmFpbGFibGUgZm9udHMgYWRkaW5nIHRob3NlIHRoYXQKICAgICAqIG1hdGNoIHRvIHRoZSBoYXNoIHRhYmxlCiAgICAgKi8KICAgIGZvciAoc2V0ID0gMDsgc2V0IDwgbnNldHM7IHNldCsrKQogICAgewoJcyA9IHNldHNbc2V0XTsKCWlmICghcykKCSAgICBjb250aW51ZTsKCWZvciAoZiA9IDA7IGYgPCBzLT5uZm9udDsgZisrKQoJICAgIGlmIChGY0xpc3RQYXR0ZXJuTWF0Y2hBbnkgKHAsIHMtPmZvbnRzW2ZdKSkKCQlpZiAoIUZjTGlzdEFwcGVuZCAoJnRhYmxlLCBzLT5mb250c1tmXSwgb3MpKQoJCSAgICBnb3RvIGJhaWwxOwogICAgfQojaWYgMAogICAgewoJaW50CW1heCA9IDA7CglpbnQJZnVsbCA9IDA7CglpbnQJZW50cyA9IDA7CglpbnQJbGVuOwoJZm9yIChpID0gMDsgaSA8IEZDX0xJU1RfSEFTSF9TSVpFOyBpKyspCgl7CgkgICAgaWYgKChidWNrZXQgPSB0YWJsZS5idWNrZXRzW2ldKSkKCSAgICB7CgkJbGVuID0gMDsKCQlmb3IgKDsgYnVja2V0OyBidWNrZXQgPSBidWNrZXQtPm5leHQpCgkJewoJCSAgICBlbnRzKys7CgkJICAgIGxlbisrOwoJCX0KCQlpZiAobGVuID4gbWF4KQoJCSAgICBtYXggPSBsZW47CgkJZnVsbCsrOwoJICAgIH0KCX0KCXByaW50ZiAoInVzZWQ6ICVkIG1heDogJWQgYXZnOiAlZ1xuIiwgZnVsbCwgbWF4LCAKCQkoZG91YmxlKSBlbnRzIC8gRkNfTElTVF9IQVNIX1NJWkUpOwogICAgfQojZW5kaWYKICAgIC8qCiAgICAgKiBXYWxrIHRoZSBoYXNoIHRhYmxlIGFuZCBidWlsZAogICAgICogYSBmb250IHNldAogICAgICovCiAgICByZXQgPSBGY0ZvbnRTZXRDcmVhdGUgKCk7CiAgICBpZiAoIXJldCkKCWdvdG8gYmFpbDA7CiAgICBmb3IgKGkgPSAwOyBpIDwgRkNfTElTVF9IQVNIX1NJWkU7IGkrKykKCXdoaWxlICgoYnVja2V0ID0gdGFibGUuYnVja2V0c1tpXSkpCgl7CgkgICAgaWYgKCFGY0ZvbnRTZXRBZGQgKHJldCwgYnVja2V0LT5wYXR0ZXJuKSkKCQlnb3RvIGJhaWwyOwoJICAgIHRhYmxlLmJ1Y2tldHNbaV0gPSBidWNrZXQtPm5leHQ7CgkgICAgRmNNZW1GcmVlIChGQ19NRU1fTElTVEJVQ0ssIHNpemVvZiAoRmNMaXN0QnVja2V0KSk7CgkgICAgZnJlZSAoYnVja2V0KTsKCX0KICAgIAogICAgcmV0dXJuIHJldDsKCmJhaWwyOgogICAgRmNGb250U2V0RGVzdHJveSAocmV0KTsKYmFpbDE6CiAgICBGY0xpc3RIYXNoVGFibGVDbGVhbnVwICgmdGFibGUpOwpiYWlsMDoKICAgIHJldHVybiAwOwp9CgpGY0ZvbnRTZXQgKgpGY0ZvbnRMaXN0IChGY0NvbmZpZwkqY29uZmlnLAoJICAgIEZjUGF0dGVybgkqcCwKCSAgICBGY09iamVjdFNldCAqb3MpCnsKICAgIEZjRm9udFNldAkqc2V0c1syXTsKICAgIGludAkJbnNldHM7CgogICAgaWYgKCFjb25maWcpCiAgICB7Cgljb25maWcgPSBGY0NvbmZpZ0dldEN1cnJlbnQgKCk7CglpZiAoIWNvbmZpZykKCSAgICByZXR1cm4gMDsKICAgIH0KICAgIG5zZXRzID0gMDsKICAgIGlmIChjb25maWctPmZvbnRzW0ZjU2V0U3lzdGVtXSkKCXNldHNbbnNldHMrK10gPSBjb25maWctPmZvbnRzW0ZjU2V0U3lzdGVtXTsKICAgIGlmIChjb25maWctPmZvbnRzW0ZjU2V0QXBwbGljYXRpb25dKQoJc2V0c1tuc2V0cysrXSA9IGNvbmZpZy0+Zm9udHNbRmNTZXRBcHBsaWNhdGlvbl07CiAgICByZXR1cm4gRmNGb250U2V0TGlzdCAoY29uZmlnLCBzZXRzLCBuc2V0cywgcCwgb3MpOwp9Cg==