LyoKICogJFhGcmVlODY6IHhjL2xpYi9mb250Y29uZmlnL3NyYy9mY2xpc3QuYyx2IDEuNSAyMDAyLzA2LzAzIDA4OjMxOjE1IGtlaXRocCBFeHAgJAogKgogKiBDb3B5cmlnaHQgqSAyMDAwIEtlaXRoIFBhY2thcmQsIG1lbWJlciBvZiBUaGUgWEZyZWU4NiBQcm9qZWN0LCBJbmMuCiAqCiAqIFBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGRpc3RyaWJ1dGUsIGFuZCBzZWxsIHRoaXMgc29mdHdhcmUgYW5kIGl0cwogKiBkb2N1bWVudGF0aW9uIGZvciBhbnkgcHVycG9zZSBpcyBoZXJlYnkgZ3JhbnRlZCB3aXRob3V0IGZlZSwgcHJvdmlkZWQgdGhhdAogKiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhcHBlYXIgaW4gYWxsIGNvcGllcyBhbmQgdGhhdCBib3RoIHRoYXQKICogY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBhcHBlYXIgaW4gc3VwcG9ydGluZwogKiBkb2N1bWVudGF0aW9uLCBhbmQgdGhhdCB0aGUgbmFtZSBvZiBLZWl0aCBQYWNrYXJkIG5vdCBiZSB1c2VkIGluCiAqIGFkdmVydGlzaW5nIG9yIHB1YmxpY2l0eSBwZXJ0YWluaW5nIHRvIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc29mdHdhcmUgd2l0aG91dAogKiBzcGVjaWZpYywgd3JpdHRlbiBwcmlvciBwZXJtaXNzaW9uLiAgS2VpdGggUGFja2FyZCBtYWtlcyBubwogKiByZXByZXNlbnRhdGlvbnMgYWJvdXQgdGhlIHN1aXRhYmlsaXR5IG9mIHRoaXMgc29mdHdhcmUgZm9yIGFueSBwdXJwb3NlLiAgSXQKICogaXMgcHJvdmlkZWQgImFzIGlzIiB3aXRob3V0IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4KICoKICogS0VJVEggUEFDS0FSRCBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSCBSRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSwKICogSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTLCBJTiBOTwogKiBFVkVOVCBTSEFMTCBLRUlUSCBQQUNLQVJEIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIElORElSRUNUIE9SCiAqIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NIExPU1MgT0YgVVNFLAogKiBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SIE9USEVSCiAqIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1IKICogUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS4KICovCgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlICJmY2ludC5oIgoKRmNPYmplY3RTZXQgKgpGY09iamVjdFNldENyZWF0ZSAodm9pZCkKewogICAgRmNPYmplY3RTZXQgICAgKm9zOwoKICAgIG9zID0gKEZjT2JqZWN0U2V0ICopIG1hbGxvYyAoc2l6ZW9mIChGY09iamVjdFNldCkpOwogICAgaWYgKCFvcykKCXJldHVybiAwOwogICAgRmNNZW1BbGxvYyAoRkNfTUVNX09CSkVDVFNFVCwgc2l6ZW9mIChGY09iamVjdFNldCkpOwogICAgb3MtPm5vYmplY3QgPSAwOwogICAgb3MtPnNvYmplY3QgPSAwOwogICAgb3MtPm9iamVjdHMgPSAwOwogICAgcmV0dXJuIG9zOwp9CgpGY0Jvb2wKRmNPYmplY3RTZXRBZGQgKEZjT2JqZWN0U2V0ICpvcywgY29uc3QgY2hhciAqb2JqZWN0KQp7CiAgICBpbnQJCXM7CiAgICBjb25zdCBjaGFyCSoqb2JqZWN0czsKICAgIGludAkJaGlnaCwgbG93LCBtaWQsIGM7CiAgICAKICAgIGlmIChvcy0+bm9iamVjdCA9PSBvcy0+c29iamVjdCkKICAgIHsKCXMgPSBvcy0+c29iamVjdCArIDQ7CglpZiAob3MtPm9iamVjdHMpCgkgICAgb2JqZWN0cyA9IChjb25zdCBjaGFyICoqKSByZWFsbG9jICgodm9pZCAqKSBvcy0+b2JqZWN0cywKCQkJCQkgICAgICAgcyAqIHNpemVvZiAoY29uc3QgY2hhciAqKSk7CgllbHNlCgkgICAgb2JqZWN0cyA9IChjb25zdCBjaGFyICoqKSBtYWxsb2MgKHMgKiBzaXplb2YgKGNvbnN0IGNoYXIgKikpOwoJaWYgKCFvYmplY3RzKQoJICAgIHJldHVybiBGY0ZhbHNlOwoJaWYgKG9zLT5zb2JqZWN0KQoJICAgIEZjTWVtRnJlZSAoRkNfTUVNX09CSkVDVFBUUiwgb3MtPnNvYmplY3QgKiBzaXplb2YgKGNvbnN0IGNoYXIgKikpOwoJRmNNZW1BbGxvYyAoRkNfTUVNX09CSkVDVFBUUiwgcyAqIHNpemVvZiAoY29uc3QgY2hhciAqKSk7Cglvcy0+b2JqZWN0cyA9IG9iamVjdHM7Cglvcy0+c29iamVjdCA9IHM7CiAgICB9CiAgICBoaWdoID0gb3MtPm5vYmplY3QgLSAxOwogICAgbG93ID0gMDsKICAgIG1pZCA9IDA7CiAgICBjID0gMTsKICAgIHdoaWxlIChsb3cgPD0gaGlnaCkKICAgIHsKCW1pZCA9IChsb3cgKyBoaWdoKSA+PiAxOwoJYyA9IHN0cmNtcCAob3MtPm9iamVjdHNbbWlkXSwgb2JqZWN0KTsKCWlmIChjID09IDApCgkgICAgcmV0dXJuIEZjVHJ1ZTsKCWlmIChjIDwgMCkKCSAgICBsb3cgPSBtaWQgKyAxOwoJZWxzZQoJICAgIGhpZ2ggPSBtaWQgLSAxOwogICAgfQogICAgaWYgKGMgPCAwKQoJbWlkKys7CiAgICBtZW1tb3ZlIChvcy0+b2JqZWN0cyArIG1pZCArIDEsIG9zLT5vYmplY3RzICsgbWlkLCAKCSAgICAgKG9zLT5ub2JqZWN0IC0gbWlkKSAqIHNpemVvZiAoY29uc3QgY2hhciAqKSk7CiAgICBvcy0+b2JqZWN0c1ttaWRdID0gb2JqZWN0OwogICAgb3MtPm5vYmplY3QrKzsKICAgIHJldHVybiBGY1RydWU7Cn0KCnZvaWQKRmNPYmplY3RTZXREZXN0cm95IChGY09iamVjdFNldCAqb3MpCnsKICAgIGlmIChvcy0+b2JqZWN0cykKICAgIHsKCUZjTWVtRnJlZSAoRkNfTUVNX09CSkVDVFBUUiwgb3MtPnNvYmplY3QgKiBzaXplb2YgKGNvbnN0IGNoYXIgKikpOwoJZnJlZSAoKHZvaWQgKikgb3MtPm9iamVjdHMpOwogICAgfQogICAgRmNNZW1GcmVlIChGQ19NRU1fT0JKRUNUU0VULCBzaXplb2YgKEZjT2JqZWN0U2V0KSk7CiAgICBmcmVlIChvcyk7Cn0KCkZjT2JqZWN0U2V0ICoKRmNPYmplY3RTZXRWYUJ1aWxkIChjb25zdCBjaGFyICpmaXJzdCwgdmFfbGlzdCB2YSkKewogICAgRmNPYmplY3RTZXQgICAgKnJldDsKCiAgICBGY09iamVjdFNldFZhcEJ1aWxkIChyZXQsIGZpcnN0LCB2YSk7CiAgICByZXR1cm4gcmV0Owp9CgpGY09iamVjdFNldCAqCkZjT2JqZWN0U2V0QnVpbGQgKGNvbnN0IGNoYXIgKmZpcnN0LCAuLi4pCnsKICAgIHZhX2xpc3QJICAgIHZhOwogICAgRmNPYmplY3RTZXQgICAgKm9zOwoKICAgIHZhX3N0YXJ0ICh2YSwgZmlyc3QpOwogICAgRmNPYmplY3RTZXRWYXBCdWlsZCAob3MsIGZpcnN0LCB2YSk7CiAgICB2YV9lbmQgKHZhKTsKICAgIHJldHVybiBvczsKfQoKc3RhdGljIEZjQm9vbApGY0xpc3RWYWx1ZUxpc3RNYXRjaEFueSAoRmNWYWx1ZUxpc3QgKnYxb3JpZywKCQkJIEZjVmFsdWVMaXN0ICp2Mm9yaWcpCnsKICAgIEZjVmFsdWVMaXN0CSAgICAqdjEsICp2MjsKCiAgICBmb3IgKHYxID0gdjFvcmlnOyB2MTsgdjEgPSB2MS0+bmV4dCkKCWZvciAodjIgPSB2Mm9yaWc7IHYyOyB2MiA9IHYyLT5uZXh0KQoJICAgIGlmIChGY0NvbmZpZ0NvbXBhcmVWYWx1ZSAodjItPnZhbHVlLCBGY09wQ29udGFpbnMsIHYxLT52YWx1ZSkpCgkJcmV0dXJuIEZjVHJ1ZTsKICAgIHJldHVybiBGY0ZhbHNlOwp9CgpzdGF0aWMgRmNCb29sCkZjTGlzdFZhbHVlTGlzdEVxdWFsIChGY1ZhbHVlTGlzdCAgICp2MW9yaWcsCgkJICAgICAgRmNWYWx1ZUxpc3QgICAqdjJvcmlnKQp7CiAgICBGY1ZhbHVlTGlzdAkgICAgKnYxLCAqdjI7CgogICAgZm9yICh2MSA9IHYxb3JpZzsgdjE7IHYxID0gdjEtPm5leHQpCiAgICB7Cglmb3IgKHYyID0gdjJvcmlnOyB2MjsgdjIgPSB2Mi0+bmV4dCkKCSAgICBpZiAoRmNDb25maWdDb21wYXJlVmFsdWUgKHYxLT52YWx1ZSwgRmNPcEVxdWFsLCB2Mi0+dmFsdWUpKQoJCWJyZWFrOwoJaWYgKCF2MikKCSAgICByZXR1cm4gRmNGYWxzZTsKICAgIH0KICAgIGZvciAodjIgPSB2Mm9yaWc7IHYyOyB2MiA9IHYyLT5uZXh0KQogICAgewoJZm9yICh2MSA9IHYxb3JpZzsgdjE7IHYxID0gdjEtPm5leHQpCgkgICAgaWYgKEZjQ29uZmlnQ29tcGFyZVZhbHVlICh2MS0+dmFsdWUsIEZjT3BFcXVhbCwgdjItPnZhbHVlKSkKCQlicmVhazsKCWlmICghdjEpCgkgICAgcmV0dXJuIEZjRmFsc2U7CiAgICB9CiAgICByZXR1cm4gRmNUcnVlOwp9CgpzdGF0aWMgRmNCb29sCkZjTGlzdFBhdHRlcm5FcXVhbCAoRmNQYXR0ZXJuCSpwMSwKCQkgICAgRmNQYXR0ZXJuCSpwMiwKCQkgICAgRmNPYmplY3RTZXQJKm9zKQp7CiAgICBpbnQJCSAgICBpOwogICAgRmNQYXR0ZXJuRWx0ICAgICplMSwgKmUyOwoKICAgIGZvciAoaSA9IDA7IGkgPCBvcy0+bm9iamVjdDsgaSsrKQogICAgewoJZTEgPSBGY1BhdHRlcm5GaW5kRWx0IChwMSwgb3MtPm9iamVjdHNbaV0pOwoJZTIgPSBGY1BhdHRlcm5GaW5kRWx0IChwMiwgb3MtPm9iamVjdHNbaV0pOwoJaWYgKCFlMSAmJiAhZTIpCgkgICAgcmV0dXJuIEZjVHJ1ZTsKCWlmICghZTEgfHwgIWUyKQoJICAgIHJldHVybiBGY0ZhbHNlOwoJaWYgKCFGY0xpc3RWYWx1ZUxpc3RFcXVhbCAoZTEtPnZhbHVlcywgZTItPnZhbHVlcykpCgkgICAgcmV0dXJuIEZjRmFsc2U7CiAgICB9CiAgICByZXR1cm4gRmNUcnVlOwp9CgovKgogKiBGY1RydWUgaWZmIGFsbCBvYmplY3RzIGluICJwIiBtYXRjaCAiZm9udCIKICovCgpzdGF0aWMgRmNCb29sCkZjTGlzdFBhdHRlcm5NYXRjaEFueSAoRmNQYXR0ZXJuICpwLAoJCSAgICAgICBGY1BhdHRlcm4gKmZvbnQpCnsKICAgIGludAkJICAgIGk7CiAgICBGY1BhdHRlcm5FbHQgICAqZTsKCiAgICBmb3IgKGkgPSAwOyBpIDwgcC0+bnVtOyBpKyspCiAgICB7CgllID0gRmNQYXR0ZXJuRmluZEVsdCAoZm9udCwgcC0+ZWx0c1tpXS5vYmplY3QpOwoJaWYgKCFlKQoJICAgIHJldHVybiBGY0ZhbHNlOwoJaWYgKCFGY0xpc3RWYWx1ZUxpc3RNYXRjaEFueSAocC0+ZWx0c1tpXS52YWx1ZXMsIGUtPnZhbHVlcykpCgkgICAgcmV0dXJuIEZjRmFsc2U7CiAgICB9CiAgICByZXR1cm4gRmNUcnVlOwp9CgpzdGF0aWMgRmNDaGFyMzIKRmNMaXN0U3RyaW5nSGFzaCAoY29uc3QgRmNDaGFyOAkqcykKewogICAgRmNDaGFyMzIJaCA9IDA7CiAgICBGY0NoYXI4CWM7CgogICAgd2hpbGUgKChjID0gKnMrKykpCiAgICB7CgljID0gRmNUb0xvd2VyIChjKTsKCWggPSAoKGggPDwgMykgXiAoaCA+PiAzKSkgXiBjOwogICAgfQogICAgcmV0dXJuIGg7Cn0KCnN0YXRpYyBGY0NoYXIzMgpGY0xpc3RNYXRyaXhIYXNoIChjb25zdCBGY01hdHJpeCAqbSkKewogICAgaW50CSAgICB4eCA9IChpbnQpIChtLT54eCAqIDEwMCksIAoJICAgIHh5ID0gKGludCkgKG0tPnh5ICogMTAwKSwgCgkgICAgeXggPSAoaW50KSAobS0+eXggKiAxMDApLAoJICAgIHl5ID0gKGludCkgKG0tPnl5ICogMTAwKTsKCiAgICByZXR1cm4gKChGY0NoYXIzMikgeHgpIF4gKChGY0NoYXIzMikgeHkpIF4gKChGY0NoYXIzMikgeXgpIF4gKChGY0NoYXIzMikgeXkpOwp9CgpzdGF0aWMgRmNDaGFyMzIKRmNMaXN0VmFsdWVIYXNoIChGY1ZhbHVlICAgIHYpCnsKICAgIHN3aXRjaCAodi50eXBlKSB7CiAgICBjYXNlIEZjVHlwZVZvaWQ6CglyZXR1cm4gMDsKICAgIGNhc2UgRmNUeXBlSW50ZWdlcjoKCXJldHVybiAoRmNDaGFyMzIpIHYudS5pOwogICAgY2FzZSBGY1R5cGVEb3VibGU6CglyZXR1cm4gKEZjQ2hhcjMyKSAoaW50KSB2LnUuZDsKICAgIGNhc2UgRmNUeXBlU3RyaW5nOgoJcmV0dXJuIEZjTGlzdFN0cmluZ0hhc2ggKHYudS5zKTsKICAgIGNhc2UgRmNUeXBlQm9vbDoKCXJldHVybiAoRmNDaGFyMzIpIHYudS5iOwogICAgY2FzZSBGY1R5cGVNYXRyaXg6CglyZXR1cm4gRmNMaXN0TWF0cml4SGFzaCAodi51Lm0pOwogICAgY2FzZSBGY1R5cGVDaGFyU2V0OgoJcmV0dXJuIEZjQ2hhclNldENvdW50ICh2LnUuYyk7CiAgICBjYXNlIEZjVHlwZUZURmFjZToKCXJldHVybiAoRmNDaGFyMzIpIHYudS5mOwogICAgfQogICAgcmV0dXJuIDA7Cn0KCnN0YXRpYyBGY0NoYXIzMgpGY0xpc3RWYWx1ZUxpc3RIYXNoIChGY1ZhbHVlTGlzdCAgICAqbGlzdCkKewogICAgRmNDaGFyMzIJaCA9IDA7CiAgICAKICAgIHdoaWxlIChsaXN0KQogICAgewoJaCA9IGggXiBGY0xpc3RWYWx1ZUhhc2ggKGxpc3QtPnZhbHVlKTsKCWxpc3QgPSBsaXN0LT5uZXh0OwogICAgfQogICAgcmV0dXJuIGg7Cn0KCnN0YXRpYyBGY0NoYXIzMgpGY0xpc3RQYXR0ZXJuSGFzaCAoRmNQYXR0ZXJuCSpmb250LAoJCSAgIEZjT2JqZWN0U2V0CSpvcykKewogICAgaW50CQkgICAgbjsKICAgIEZjUGF0dGVybkVsdCAgICAqZTsKICAgIEZjQ2hhcjMyCSAgICBoID0gMDsKCiAgICBmb3IgKG4gPSAwOyBuIDwgb3MtPm5vYmplY3Q7IG4rKykKICAgIHsKCWUgPSBGY1BhdHRlcm5GaW5kRWx0IChmb250LCBvcy0+b2JqZWN0c1tuXSk7CglpZiAoZSkKCSAgICBoID0gaCBeIEZjTGlzdFZhbHVlTGlzdEhhc2ggKGUtPnZhbHVlcyk7CiAgICB9CiAgICByZXR1cm4gaDsKfQoKdHlwZWRlZiBzdHJ1Y3QgX0ZjTGlzdEJ1Y2tldCB7CiAgICBzdHJ1Y3QgX0ZjTGlzdEJ1Y2tldCAgICAqbmV4dDsKICAgIEZjQ2hhcjMyCQkgICAgaGFzaDsKICAgIEZjUGF0dGVybgkJICAgICpwYXR0ZXJuOwp9IEZjTGlzdEJ1Y2tldDsKCiNkZWZpbmUgRkNfTElTVF9IQVNIX1NJWkUgICA0MDk5Cgp0eXBlZGVmIHN0cnVjdCBfRmNMaXN0SGFzaFRhYmxlIHsKICAgIGludAkJICAgIGVudHJpZXM7CiAgICBGY0xpc3RCdWNrZXQgICAgKmJ1Y2tldHNbRkNfTElTVF9IQVNIX1NJWkVdOwp9IEZjTGlzdEhhc2hUYWJsZTsKICAgIApzdGF0aWMgdm9pZApGY0xpc3RIYXNoVGFibGVJbml0IChGY0xpc3RIYXNoVGFibGUgKnRhYmxlKQp7CiAgICB0YWJsZS0+ZW50cmllcyA9IDA7CiAgICBtZW1zZXQgKHRhYmxlLT5idWNrZXRzLCAnXDAnLCBzaXplb2YgKHRhYmxlLT5idWNrZXRzKSk7Cn0KCnN0YXRpYyB2b2lkCkZjTGlzdEhhc2hUYWJsZUNsZWFudXAgKEZjTGlzdEhhc2hUYWJsZSAqdGFibGUpCnsKICAgIGludAlpOwogICAgRmNMaXN0QnVja2V0ICAgICpidWNrZXQsICpuZXh0OwoKICAgIGZvciAoaSA9IDA7IGkgPCBGQ19MSVNUX0hBU0hfU0laRTsgaSsrKQogICAgewoJZm9yIChidWNrZXQgPSB0YWJsZS0+YnVja2V0c1tpXTsgYnVja2V0OyBidWNrZXQgPSBuZXh0KQoJewoJICAgIG5leHQgPSBidWNrZXQtPm5leHQ7CgkgICAgRmNQYXR0ZXJuRGVzdHJveSAoYnVja2V0LT5wYXR0ZXJuKTsKCSAgICBGY01lbUZyZWUgKEZDX01FTV9MSVNUQlVDSywgc2l6ZW9mIChGY0xpc3RCdWNrZXQpKTsKCSAgICBmcmVlIChidWNrZXQpOwoJfQoJdGFibGUtPmJ1Y2tldHNbaV0gPSAwOwogICAgfQogICAgdGFibGUtPmVudHJpZXMgPSAwOwp9CgpzdGF0aWMgRmNCb29sCkZjTGlzdEFwcGVuZCAoRmNMaXN0SGFzaFRhYmxlCSp0YWJsZSwKCSAgICAgIEZjUGF0dGVybgkJKmZvbnQsCgkgICAgICBGY09iamVjdFNldAkqb3MpCnsKICAgIGludAkJICAgIG87CiAgICBGY1BhdHRlcm5FbHQgICAgKmU7CiAgICBGY1ZhbHVlTGlzdAkgICAgKnY7CiAgICBGY0NoYXIzMgkgICAgaGFzaDsKICAgIEZjTGlzdEJ1Y2tldCAgICAqKnByZXYsICpidWNrZXQ7CgogICAgaGFzaCA9IEZjTGlzdFBhdHRlcm5IYXNoIChmb250LCBvcyk7CiAgICBmb3IgKHByZXYgPSAmdGFibGUtPmJ1Y2tldHNbaGFzaCAlIEZDX0xJU1RfSEFTSF9TSVpFXTsKCSAoYnVja2V0ID0gKnByZXYpOyBwcmV2ID0gJihidWNrZXQtPm5leHQpKQogICAgewoJaWYgKGJ1Y2tldC0+aGFzaCA9PSBoYXNoICYmIAoJICAgIEZjTGlzdFBhdHRlcm5FcXVhbCAoYnVja2V0LT5wYXR0ZXJuLCBmb250LCBvcykpCgkgICAgcmV0dXJuIEZjVHJ1ZTsKICAgIH0KICAgIGJ1Y2tldCA9IChGY0xpc3RCdWNrZXQgKikgbWFsbG9jIChzaXplb2YgKEZjTGlzdEJ1Y2tldCkpOwogICAgaWYgKCFidWNrZXQpCglnb3RvIGJhaWwwOwogICAgRmNNZW1BbGxvYyAoRkNfTUVNX0xJU1RCVUNLLCBzaXplb2YgKEZjTGlzdEJ1Y2tldCkpOwogICAgYnVja2V0LT5uZXh0ID0gMDsKICAgIGJ1Y2tldC0+aGFzaCA9IGhhc2g7CiAgICBidWNrZXQtPnBhdHRlcm4gPSBGY1BhdHRlcm5DcmVhdGUgKCk7CiAgICBpZiAoIWJ1Y2tldC0+cGF0dGVybikKCWdvdG8gYmFpbDE7CiAgICAKICAgIGZvciAobyA9IDA7IG8gPCBvcy0+bm9iamVjdDsgbysrKQogICAgewoJZSA9IEZjUGF0dGVybkZpbmRFbHQgKGZvbnQsIG9zLT5vYmplY3RzW29dKTsKCWlmIChlKQoJewoJICAgIGZvciAodiA9IGUtPnZhbHVlczsgdjsgdiA9IHYtPm5leHQpCgkgICAgewoJCWlmICghRmNQYXR0ZXJuQWRkIChidWNrZXQtPnBhdHRlcm4sIAoJCQkJICAgb3MtPm9iamVjdHNbb10sIAoJCQkJICAgdi0+dmFsdWUsIEZjVHJ1ZSkpCgkJICAgIGdvdG8gYmFpbDI7CgkgICAgfQoJfQogICAgfQogICAgKnByZXYgPSBidWNrZXQ7CiAgICArK3RhYmxlLT5lbnRyaWVzOwoKICAgIHJldHVybiBGY1RydWU7CiAgICAKYmFpbDI6CiAgICBGY1BhdHRlcm5EZXN0cm95IChidWNrZXQtPnBhdHRlcm4pOwpiYWlsMToKICAgIEZjTWVtRnJlZSAoRkNfTUVNX0xJU1RCVUNLLCBzaXplb2YgKEZjTGlzdEJ1Y2tldCkpOwogICAgZnJlZSAoYnVja2V0KTsKYmFpbDA6CiAgICByZXR1cm4gRmNGYWxzZTsKfQoKRmNGb250U2V0ICoKRmNGb250U2V0TGlzdCAoRmNDb25maWcJICAgICpjb25maWcsCgkgICAgICAgRmNGb250U2V0ICAgICoqc2V0cywKCSAgICAgICBpbnQJICAgIG5zZXRzLAoJICAgICAgIEZjUGF0dGVybiAgICAqcCwKCSAgICAgICBGY09iamVjdFNldCAgKm9zKQp7CiAgICBGY0ZvbnRTZXQJICAgICpyZXQ7CiAgICBGY0ZvbnRTZXQJICAgICpzOwogICAgaW50CQkgICAgZjsKICAgIGludAkJICAgIHNldDsKICAgIEZjTGlzdEhhc2hUYWJsZSB0YWJsZTsKICAgIGludAkJICAgIGk7CiAgICBGY0xpc3RCdWNrZXQgICAgKmJ1Y2tldDsKCiAgICBpZiAoIWNvbmZpZykKICAgIHsKCWlmICghRmNJbml0QnJpbmdVcHRvRGF0ZSAoKSkKCSAgICBnb3RvIGJhaWwwOwoKCWNvbmZpZyA9IEZjQ29uZmlnR2V0Q3VycmVudCAoKTsKCWlmICghY29uZmlnKQoJICAgIGdvdG8gYmFpbDA7CiAgICB9CiAgICBGY0xpc3RIYXNoVGFibGVJbml0ICgmdGFibGUpOwogICAgLyoKICAgICAqIFdhbGsgYWxsIGF2YWlsYWJsZSBmb250cyBhZGRpbmcgdGhvc2UgdGhhdAogICAgICogbWF0Y2ggdG8gdGhlIGhhc2ggdGFibGUKICAgICAqLwogICAgZm9yIChzZXQgPSAwOyBzZXQgPCBuc2V0czsgc2V0KyspCiAgICB7CglzID0gc2V0c1tzZXRdOwoJaWYgKCFzKQoJICAgIGNvbnRpbnVlOwoJZm9yIChmID0gMDsgZiA8IHMtPm5mb250OyBmKyspCgkgICAgaWYgKEZjTGlzdFBhdHRlcm5NYXRjaEFueSAocCwgcy0+Zm9udHNbZl0pKQoJCWlmICghRmNMaXN0QXBwZW5kICgmdGFibGUsIHMtPmZvbnRzW2ZdLCBvcykpCgkJICAgIGdvdG8gYmFpbDE7CiAgICB9CiNpZiAwCiAgICB7CglpbnQJbWF4ID0gMDsKCWludAlmdWxsID0gMDsKCWludAllbnRzID0gMDsKCWludAlsZW47Cglmb3IgKGkgPSAwOyBpIDwgRkNfTElTVF9IQVNIX1NJWkU7IGkrKykKCXsKCSAgICBpZiAoKGJ1Y2tldCA9IHRhYmxlLmJ1Y2tldHNbaV0pKQoJICAgIHsKCQlsZW4gPSAwOwoJCWZvciAoOyBidWNrZXQ7IGJ1Y2tldCA9IGJ1Y2tldC0+bmV4dCkKCQl7CgkJICAgIGVudHMrKzsKCQkgICAgbGVuKys7CgkJfQoJCWlmIChsZW4gPiBtYXgpCgkJICAgIG1heCA9IGxlbjsKCQlmdWxsKys7CgkgICAgfQoJfQoJcHJpbnRmICgidXNlZDogJWQgbWF4OiAlZCBhdmc6ICVnXG4iLCBmdWxsLCBtYXgsIAoJCShkb3VibGUpIGVudHMgLyBGQ19MSVNUX0hBU0hfU0laRSk7CiAgICB9CiNlbmRpZgogICAgLyoKICAgICAqIFdhbGsgdGhlIGhhc2ggdGFibGUgYW5kIGJ1aWxkCiAgICAgKiBhIGZvbnQgc2V0CiAgICAgKi8KICAgIHJldCA9IEZjRm9udFNldENyZWF0ZSAoKTsKICAgIGlmICghcmV0KQoJZ290byBiYWlsMDsKICAgIGZvciAoaSA9IDA7IGkgPCBGQ19MSVNUX0hBU0hfU0laRTsgaSsrKQoJd2hpbGUgKChidWNrZXQgPSB0YWJsZS5idWNrZXRzW2ldKSkKCXsKCSAgICBpZiAoIUZjRm9udFNldEFkZCAocmV0LCBidWNrZXQtPnBhdHRlcm4pKQoJCWdvdG8gYmFpbDI7CgkgICAgdGFibGUuYnVja2V0c1tpXSA9IGJ1Y2tldC0+bmV4dDsKCSAgICBGY01lbUZyZWUgKEZDX01FTV9MSVNUQlVDSywgc2l6ZW9mIChGY0xpc3RCdWNrZXQpKTsKCSAgICBmcmVlIChidWNrZXQpOwoJfQogICAgCiAgICByZXR1cm4gcmV0OwoKYmFpbDI6CiAgICBGY0ZvbnRTZXREZXN0cm95IChyZXQpOwpiYWlsMToKICAgIEZjTGlzdEhhc2hUYWJsZUNsZWFudXAgKCZ0YWJsZSk7CmJhaWwwOgogICAgcmV0dXJuIDA7Cn0KCkZjRm9udFNldCAqCkZjRm9udExpc3QgKEZjQ29uZmlnCSpjb25maWcsCgkgICAgRmNQYXR0ZXJuCSpwLAoJICAgIEZjT2JqZWN0U2V0ICpvcykKewogICAgRmNGb250U2V0CSpzZXRzWzJdOwogICAgaW50CQluc2V0czsKCiAgICBpZiAoIWNvbmZpZykKICAgIHsKCWNvbmZpZyA9IEZjQ29uZmlnR2V0Q3VycmVudCAoKTsKCWlmICghY29uZmlnKQoJICAgIHJldHVybiAwOwogICAgfQogICAgbnNldHMgPSAwOwogICAgaWYgKGNvbmZpZy0+Zm9udHNbRmNTZXRTeXN0ZW1dKQoJc2V0c1tuc2V0cysrXSA9IGNvbmZpZy0+Zm9udHNbRmNTZXRTeXN0ZW1dOwogICAgaWYgKGNvbmZpZy0+Zm9udHNbRmNTZXRBcHBsaWNhdGlvbl0pCglzZXRzW25zZXRzKytdID0gY29uZmlnLT5mb250c1tGY1NldEFwcGxpY2F0aW9uXTsKICAgIHJldHVybiBGY0ZvbnRTZXRMaXN0IChjb25maWcsIHNldHMsIG5zZXRzLCBwLCBvcyk7Cn0K