X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f X-Recipient: djgpp AT delorie DOT com X-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=+JT9sW0foPo1jJ14CAGo7q8NLa/Ei5AZAn58EAnXYU8=; b=IRJGwPTQgc08E2r1jlDVrrr0vd3nSAdBa7DyVuqQuW7BuHzpickt8BXlBb0N3ZAAGq 6nPJ/AwzhST5Yfxa+w+I97K6LLQRsyQYCt+MD9+er3SBbvaC5ARv50V5aRUfdWXyxvdP DQ83PLJon/4UxvwTb0jr9STfy3QMtCko1xik9a+rtMqQmIiGbZbgR019TZZKWSkQ/NOu p9Af/nBKZ6qe5xvU+radoAYsB9mKckYVAUP+pi3K0gwOnZLJOeycaHa6g3aHxR5ShHaU 3RDef41Ai4Lj0tcy0bLSDoafEIf+7hO+354gr0OLqkEZsjxxXCDXRc0uTj/pX2HsmPAn X0KQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=+JT9sW0foPo1jJ14CAGo7q8NLa/Ei5AZAn58EAnXYU8=; b=OlTNg4zdEf2etmA5TTGECQqGspOvA2Tl1kMYqVjn1J3VD8kqWOj48cmZWjHut3Yu7h F8RkfWcrU3h+ivvS6yObfrYRLcBEkxEt/L9IP2vguE6PFkWjEYY2xGZCePDMVu4gbmga waUrULxruq0cu30DfTweC5iSGLHPTULz/zBZlhN1wXlZCZqErNhhySZ6xp2LUkO22ZVg i3/K3gNQm8yWPTUy38CvMlMPa4VJ3s5c5K8As0MRe6GMkFk96QGC2eH7ePNKVEuFzKDS g9eZJjXGBbLBXQgf+zgKGbwojPfTLefXWOeKmodzUJxLYx0gDqnRBXa+gN5dEnd86hGi 0HTQ== X-Gm-Message-State: AFqh2kpf+ff+uJJov74YhMurrDTVcJzdOx4iHN4cAmtx0Vg2H3gI9RpK pQ9rOt4d9/xrvg6BUFpmCz+uf6Ef0BFHHNySzyltaOXj X-Google-Smtp-Source: AMrXdXtXoKI2N477xPZl47gup6+GgO4P+VpaQEm6kZ1F9WE7BqvMFQB/mo8mduU9YQqQ36EtyhCo8NtAMKdRj+AWl54= X-Received: by 2002:a05:600c:4ca7:b0:3cf:7b68:631 with SMTP id g39-20020a05600c4ca700b003cf7b680631mr2414717wmp.55.1675099672056; Mon, 30 Jan 2023 09:27:52 -0800 (PST) MIME-Version: 1.0 From: "Ozkan Sezer (sezeroz AT gmail DOT com) [via djgpp AT delorie DOT com]" Date: Mon, 30 Jan 2023 20:27:51 +0300 Message-ID: Subject: [PATCH] dxe3gen: add support for using an exports file. To: djgpp AT delorie DOT com Content-Type: multipart/mixed; boundary="000000000000eaaa5a05f37e8882" Reply-To: djgpp AT delorie DOT com --000000000000eaaa5a05f37e8882 Content-Type: text/plain; charset="UTF-8" The patch inlined below (also attached for convenience) adds support for using an exports file to dxe3gen. The existing mechanism for exported symbols is through symbol prefixes, i.e. the -E and -X switches, but can be really hard to use especially if there are many symbols which don't necessarily share a common prefix, or if some of the symbols to exclude share the common prefix with symbols to export. The exports file is a plain text file with one symbol name at each line, like an exports file that can be used in macOS projects. No trailing or leading space/tab should be used in the file. A line starting with a '#' character is a comment line and will be ignored. The -E and -X switches are still supported, but those two are mutually exclusive. Eli, Juan, DJ: Please review. OK to apply? Index: dxe3gen.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/dxe/dxe3gen.c,v retrieving revision 1.27 diff -u -p -r1.27 dxe3gen.c --- djgpp/src/dxe/dxe3gen.c 28 Jan 2023 14:10:03 -0000 1.27 +++ djgpp/src/dxe/dxe3gen.c 30 Jan 2023 17:10:28 -0000 @@ -277,6 +277,9 @@ static struct char *implib; /* name of import library */ char *dxefile; /* the name of dxe file on command line */ char *description; /* a description of the module */ + unsigned int num_names; /* number of exported symbol names */ + unsigned int max_names; /* maximal number of exported symbol names */ + char **export_names; /* exported symbol names */ unsigned int num_prefix; /* number of exported prefixes */ unsigned int max_prefix; /* maximal number of exported prefixes */ char **export_prefix; /* exported symbol prefixes */ @@ -307,6 +310,9 @@ static struct NULL, 0, 0, + NULL, + 0, + 0, NULL }; @@ -319,6 +325,8 @@ static char *dxe_ar; /* default: "ar" */ static char *dxe_ld; /* default: "ld" */ /* linker script */ static char *dxe_sc; /* default: "dxe.ld" */ +/* exports file */ +static char *expfile; /* Desc: replaces backslash with slash in a path @@ -422,6 +430,7 @@ static void display_help(void) printf("-X prefix\tExclude symbols that start with (cumulative)\n"); printf("-U\t\tAllow unresolved symbols in DXE file\n"); printf("-V\t\tVerbose output (minimal output by default)\n"); + printf("--exports file\tExport symbols from this file (mutually exclusive with -E/-X)\n"); printf("--show-dep\tShow dependencies for specified module\n"); printf("--show-exp\tShow symbols exported by the DXE module\n"); printf("--show-unres\tShow unresolved symbols in the DXE module\n"); @@ -465,6 +474,57 @@ static void process_env(void) } +/* Desc: process the exports file pointed to by --exports option. + * + * In : - + * Out : - + * + * Note: - + */ +static void process_exp_file(const char *name) +{ + FILE *f = fopen(name, "rb"); + char *ptr; + long len; + + if (!f) + { + fprintf(stderr, "Error: Couldn't open exports file %s.\n", name); + exit(1); + } + + fseek(f, 0, SEEK_END); + len = ftell(f); + fseek(f, 0, SEEK_SET); + expfile = malloc(len + 1); + fread(expfile, 1, len, f); + fclose(f); + expfile[len] = '\0'; + + for (ptr = expfile; ; ) + { + while (*ptr == '\r' || *ptr == '\n') + *ptr++ = '\0'; + + if (!*ptr) break; + + if (*ptr == '#') /* comment */ + goto loc1; + + if (opt.num_names >= opt.max_names) + { + opt.max_names += 16; + opt.export_names = (char **)realloc(opt.export_names, opt.max_names * sizeof(char *)); + } + opt.export_names[opt.num_names++] = ptr++; + + loc1: + while (*ptr != '\r' && *ptr != '\n') + ++ptr; + } +} + + /* Desc: process command line args * * In : no of arguments, argument list, ptr to store linker args @@ -475,6 +535,7 @@ static void process_env(void) static void process_args(int argc, char *argv[], const char *new_argv[]) { int i, new_argc = NUMBER_OF_LINKER_ARGS; + int use_exports = 0; if (!libdir) { @@ -482,6 +543,17 @@ static void process_args(int argc, char exit(1); } + for (i = 1; i < argc; ++i) + { + if (!strcmp(argv[i], "--exports")) + ++use_exports; + } + if (use_exports > 1) + { + fprintf(stderr, "Error: multiple --exports arguments not allowed.\n"); + exit(1); + } + new_argv[0] = dxe_ld; new_argv[1] = "-X"; new_argv[2] = "-S"; @@ -513,6 +585,11 @@ static void process_args(int argc, char printf("Usage: %s output.dxe symbol input.o [input2.o ... -lgcc -lc]\n", progname); exit(-1); } + if (use_exports) + { + fprintf(stderr, "Error: --exports not allowed in legacy mode.\n"); + exit(1); + } opt.max_prefix = 16; opt.export_prefix = (char **)malloc(opt.max_prefix * sizeof(char *)); @@ -552,8 +629,13 @@ static void process_args(int argc, char opt.implib = argv[++i]; opt.autoresolve = TRUE; } + else if (!strcmp(argv[i], "--exports")) + { + process_exp_file(argv[++i]); + } else if (!strcmp(argv[i], "-E")) { + if (use_exports) goto bad_exports; if (opt.num_prefix >= opt.max_prefix) { opt.max_prefix += 16; @@ -563,6 +645,11 @@ static void process_args(int argc, char } else if (!strcmp(argv[i], "-X")) { + if (use_exports) + { bad_exports: + fprintf(stderr, "Error: --exports and -E / -X options are mutually exclusive\n"); + exit(1); + } if (opt.num_excl >= opt.max_excl) { opt.max_excl += 16; @@ -1185,6 +1272,21 @@ static int write_dxe(FILE *inf, FILE *ou continue; } + if (opt.num_names) + { + BOOL ok = FALSE; + for (j = 0; j < opt.num_names; j++) + { + if (strcmp(opt.export_names[j], name) == 0) + { + ok = TRUE; + break; + } + } + if (!ok) + continue; + } + /* exported symbol */ dh.n_exp_syms++; --000000000000eaaa5a05f37e8882 Content-Type: text/x-patch; charset="US-ASCII"; name="exports.patch" Content-Disposition: attachment; filename="exports.patch" Content-Transfer-Encoding: base64 X-Attachment-Id: file0 SW5kZXg6IGR4ZTNnZW4uYwo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09ClJDUyBmaWxlOiAvY3ZzL2RqZ3BwL2RqZ3BwL3Ny Yy9keGUvZHhlM2dlbi5jLHYKcmV0cmlldmluZyByZXZpc2lvbiAxLjI3CmRpZmYgLXUgLXAgLXIx LjI3IGR4ZTNnZW4uYwotLS0gZGpncHAvc3JjL2R4ZS9keGUzZ2VuLmMJMjggSmFuIDIwMjMgMTQ6 MTA6MDMgLTAwMDAJMS4yNworKysgZGpncHAvc3JjL2R4ZS9keGUzZ2VuLmMJMzAgSmFuIDIwMjMg MTc6MTA6MjggLTAwMDAKQEAgLTI3Nyw2ICsyNzcsOSBAQCBzdGF0aWMgc3RydWN0CiAgIGNoYXIg KmltcGxpYjsgICAgICAgICAgICAgICAgIC8qIG5hbWUgb2YgaW1wb3J0IGxpYnJhcnkgKi8KICAg Y2hhciAqZHhlZmlsZTsgICAgICAgICAgICAgICAgLyogdGhlIG5hbWUgb2YgZHhlIGZpbGUgb24g Y29tbWFuZCBsaW5lICovCiAgIGNoYXIgKmRlc2NyaXB0aW9uOyAgICAgICAgICAgIC8qIGEgZGVz Y3JpcHRpb24gb2YgdGhlIG1vZHVsZSAqLworICB1bnNpZ25lZCBpbnQgbnVtX25hbWVzOyAgICAg ICAvKiBudW1iZXIgb2YgZXhwb3J0ZWQgc3ltYm9sIG5hbWVzICovCisgIHVuc2lnbmVkIGludCBt YXhfbmFtZXM7ICAgICAgIC8qIG1heGltYWwgbnVtYmVyIG9mIGV4cG9ydGVkIHN5bWJvbCBuYW1l cyAqLworICBjaGFyICoqZXhwb3J0X25hbWVzOyAgICAgICAgICAvKiBleHBvcnRlZCBzeW1ib2wg bmFtZXMgKi8KICAgdW5zaWduZWQgaW50IG51bV9wcmVmaXg7ICAgICAgLyogbnVtYmVyIG9mIGV4 cG9ydGVkIHByZWZpeGVzICovCiAgIHVuc2lnbmVkIGludCBtYXhfcHJlZml4OyAgICAgIC8qIG1h eGltYWwgbnVtYmVyIG9mIGV4cG9ydGVkIHByZWZpeGVzICovCiAgIGNoYXIgKipleHBvcnRfcHJl Zml4OyAgICAgICAgIC8qIGV4cG9ydGVkIHN5bWJvbCBwcmVmaXhlcyAqLwpAQCAtMzA3LDYgKzMx MCw5IEBAIHN0YXRpYyBzdHJ1Y3QKICAgTlVMTCwKICAgMCwKICAgMCwKKyAgTlVMTCwKKyAgMCwK KyAgMCwKICAgTlVMTAogfTsKIApAQCAtMzE5LDYgKzMyNSw4IEBAIHN0YXRpYyBjaGFyICpkeGVf YXI7IC8qIGRlZmF1bHQ6ICJhciIgKi8KIHN0YXRpYyBjaGFyICpkeGVfbGQ7IC8qIGRlZmF1bHQ6 ICJsZCIgKi8KIC8qIGxpbmtlciBzY3JpcHQgKi8KIHN0YXRpYyBjaGFyICpkeGVfc2M7IC8qIGRl ZmF1bHQ6ICJkeGUubGQiICovCisvKiBleHBvcnRzIGZpbGUgKi8KK3N0YXRpYyBjaGFyICpleHBm aWxlOwogCiAKIC8qIERlc2M6IHJlcGxhY2VzIGJhY2tzbGFzaCB3aXRoIHNsYXNoIGluIGEgcGF0 aApAQCAtNDIyLDYgKzQzMCw3IEBAIHN0YXRpYyB2b2lkIGRpc3BsYXlfaGVscCh2b2lkKQogICBw cmludGYoIi1YIHByZWZpeFx0RXhjbHVkZSBzeW1ib2xzIHRoYXQgc3RhcnQgd2l0aCA8cHJlZml4 PiAoY3VtdWxhdGl2ZSlcbiIpOwogICBwcmludGYoIi1VXHRcdEFsbG93IHVucmVzb2x2ZWQgc3lt Ym9scyBpbiBEWEUgZmlsZVxuIik7CiAgIHByaW50ZigiLVZcdFx0VmVyYm9zZSBvdXRwdXQgKG1p bmltYWwgb3V0cHV0IGJ5IGRlZmF1bHQpXG4iKTsKKyAgcHJpbnRmKCItLWV4cG9ydHMgZmlsZVx0 RXhwb3J0IHN5bWJvbHMgZnJvbSB0aGlzIGZpbGUgKG11dHVhbGx5IGV4Y2x1c2l2ZSB3aXRoIC1F Ly1YKVxuIik7CiAgIHByaW50ZigiLS1zaG93LWRlcFx0U2hvdyBkZXBlbmRlbmNpZXMgZm9yIHNw ZWNpZmllZCBtb2R1bGVcbiIpOwogICBwcmludGYoIi0tc2hvdy1leHBcdFNob3cgc3ltYm9scyBl eHBvcnRlZCBieSB0aGUgRFhFIG1vZHVsZVxuIik7CiAgIHByaW50ZigiLS1zaG93LXVucmVzXHRT aG93IHVucmVzb2x2ZWQgc3ltYm9scyBpbiB0aGUgRFhFIG1vZHVsZVxuIik7CkBAIC00NjUsNiAr NDc0LDU3IEBAIHN0YXRpYyB2b2lkIHByb2Nlc3NfZW52KHZvaWQpCiB9CiAKIAorLyogRGVzYzog cHJvY2VzcyB0aGUgZXhwb3J0cyBmaWxlIHBvaW50ZWQgdG8gYnkgLS1leHBvcnRzIG9wdGlvbi4K KyAqCisgKiBJbiAgOiAtCisgKiBPdXQgOiAtCisgKgorICogTm90ZTogLQorICovCitzdGF0aWMg dm9pZCBwcm9jZXNzX2V4cF9maWxlKGNvbnN0IGNoYXIgKm5hbWUpCit7CisgIEZJTEUgKmYgPSBm b3BlbihuYW1lLCAicmIiKTsKKyAgY2hhciAqcHRyOworICBsb25nIGxlbjsKKworICBpZiAoIWYp CisgIHsKKyAgICBmcHJpbnRmKHN0ZGVyciwgIkVycm9yOiBDb3VsZG4ndCBvcGVuIGV4cG9ydHMg ZmlsZSAlcy5cbiIsIG5hbWUpOworICAgIGV4aXQoMSk7CisgIH0KKworICBmc2VlayhmLCAwLCBT RUVLX0VORCk7CisgIGxlbiA9IGZ0ZWxsKGYpOworICBmc2VlayhmLCAwLCBTRUVLX1NFVCk7Cisg IGV4cGZpbGUgPSBtYWxsb2MobGVuICsgMSk7CisgIGZyZWFkKGV4cGZpbGUsIDEsIGxlbiwgZik7 CisgIGZjbG9zZShmKTsKKyAgZXhwZmlsZVtsZW5dID0gJ1wwJzsKKworICBmb3IgKHB0ciA9IGV4 cGZpbGU7IDsgKQorICB7CisgICAgd2hpbGUgKCpwdHIgPT0gJ1xyJyB8fCAqcHRyID09ICdcbicp CisgICAgICAqcHRyKysgPSAnXDAnOworCisgICAgaWYgKCEqcHRyKSBicmVhazsKKworICAgIGlm ICgqcHRyID09ICcjJykgLyogY29tbWVudCAqLworICAgICAgZ290byBsb2MxOworCisgICAgaWYg KG9wdC5udW1fbmFtZXMgPj0gb3B0Lm1heF9uYW1lcykKKyAgICB7CisgICAgICBvcHQubWF4X25h bWVzICs9IDE2OworICAgICAgb3B0LmV4cG9ydF9uYW1lcyA9IChjaGFyICoqKXJlYWxsb2Mob3B0 LmV4cG9ydF9uYW1lcywgb3B0Lm1heF9uYW1lcyAqIHNpemVvZihjaGFyICopKTsKKyAgICB9Cisg ICAgb3B0LmV4cG9ydF9uYW1lc1tvcHQubnVtX25hbWVzKytdID0gcHRyKys7CisKKyAgICBsb2Mx OgorICAgIHdoaWxlICgqcHRyICE9ICdccicgJiYgKnB0ciAhPSAnXG4nKQorICAgICAgKytwdHI7 CisgIH0KK30KKworCiAvKiBEZXNjOiBwcm9jZXNzIGNvbW1hbmQgbGluZSBhcmdzCiAgKgogICog SW4gIDogbm8gb2YgYXJndW1lbnRzLCBhcmd1bWVudCBsaXN0LCBwdHIgdG8gc3RvcmUgbGlua2Vy IGFyZ3MKQEAgLTQ3NSw2ICs1MzUsNyBAQCBzdGF0aWMgdm9pZCBwcm9jZXNzX2Vudih2b2lkKQog c3RhdGljIHZvaWQgcHJvY2Vzc19hcmdzKGludCBhcmdjLCBjaGFyICphcmd2W10sIGNvbnN0IGNo YXIgKm5ld19hcmd2W10pCiB7CiAgIGludCBpLCBuZXdfYXJnYyA9IE5VTUJFUl9PRl9MSU5LRVJf QVJHUzsKKyAgaW50IHVzZV9leHBvcnRzID0gMDsKIAogICBpZiAoIWxpYmRpcikKICAgewpAQCAt NDgyLDYgKzU0MywxNyBAQCBzdGF0aWMgdm9pZCBwcm9jZXNzX2FyZ3MoaW50IGFyZ2MsIGNoYXIg CiAgICAgZXhpdCgxKTsKICAgfQogCisgIGZvciAoaSA9IDE7IGkgPCBhcmdjOyArK2kpCisgIHsK KyAgICAgaWYgKCFzdHJjbXAoYXJndltpXSwgIi0tZXhwb3J0cyIpKQorICAgICAgICsrdXNlX2V4 cG9ydHM7CisgIH0KKyAgaWYgKHVzZV9leHBvcnRzID4gMSkKKyAgeworICAgIGZwcmludGYoc3Rk ZXJyLCAiRXJyb3I6IG11bHRpcGxlIC0tZXhwb3J0cyBhcmd1bWVudHMgbm90IGFsbG93ZWQuXG4i KTsKKyAgICBleGl0KDEpOworICB9CisKICAgbmV3X2FyZ3ZbMF0gPSBkeGVfbGQ7CiAgIG5ld19h cmd2WzFdID0gIi1YIjsKICAgbmV3X2FyZ3ZbMl0gPSAiLVMiOwpAQCAtNTEzLDYgKzU4NSwxMSBA QCBzdGF0aWMgdm9pZCBwcm9jZXNzX2FyZ3MoaW50IGFyZ2MsIGNoYXIgCiAgICAgICBwcmludGYo IlVzYWdlOiAlcyBvdXRwdXQuZHhlIHN5bWJvbCBpbnB1dC5vIFtpbnB1dDIubyAuLi4gLWxnY2Mg LWxjXVxuIiwgcHJvZ25hbWUpOwogICAgICAgZXhpdCgtMSk7CiAgICAgfQorICAgIGlmICh1c2Vf ZXhwb3J0cykKKyAgICB7CisgICAgICBmcHJpbnRmKHN0ZGVyciwgIkVycm9yOiAtLWV4cG9ydHMg bm90IGFsbG93ZWQgaW4gbGVnYWN5IG1vZGUuXG4iKTsKKyAgICAgIGV4aXQoMSk7CisgICAgfQog CiAgICAgb3B0Lm1heF9wcmVmaXggPSAxNjsKICAgICBvcHQuZXhwb3J0X3ByZWZpeCA9IChjaGFy ICoqKW1hbGxvYyhvcHQubWF4X3ByZWZpeCAqIHNpemVvZihjaGFyICopKTsKQEAgLTU1Miw4ICs2 MjksMTMgQEAgc3RhdGljIHZvaWQgcHJvY2Vzc19hcmdzKGludCBhcmdjLCBjaGFyIAogICAgICAg ICBvcHQuaW1wbGliID0gYXJndlsrK2ldOwogICAgICAgICBvcHQuYXV0b3Jlc29sdmUgPSBUUlVF OwogICAgICAgfQorICAgICAgZWxzZSBpZiAoIXN0cmNtcChhcmd2W2ldLCAiLS1leHBvcnRzIikp CisgICAgICB7CisgICAgICAgIHByb2Nlc3NfZXhwX2ZpbGUoYXJndlsrK2ldKTsKKyAgICAgIH0K ICAgICAgIGVsc2UgaWYgKCFzdHJjbXAoYXJndltpXSwgIi1FIikpCiAgICAgICB7CisgICAgICAg IGlmICh1c2VfZXhwb3J0cykgZ290byBiYWRfZXhwb3J0czsKICAgICAgICAgaWYgKG9wdC5udW1f cHJlZml4ID49IG9wdC5tYXhfcHJlZml4KQogICAgICAgICB7CiAgICAgICAgICAgb3B0Lm1heF9w cmVmaXggKz0gMTY7CkBAIC01NjMsNiArNjQ1LDExIEBAIHN0YXRpYyB2b2lkIHByb2Nlc3NfYXJn cyhpbnQgYXJnYywgY2hhciAKICAgICAgIH0KICAgICAgIGVsc2UgaWYgKCFzdHJjbXAoYXJndltp XSwgIi1YIikpCiAgICAgICB7CisgICAgICAgIGlmICh1c2VfZXhwb3J0cykKKyAgICAgICAgeyBi YWRfZXhwb3J0czoKKyAgICAgICAgICBmcHJpbnRmKHN0ZGVyciwgIkVycm9yOiAtLWV4cG9ydHMg YW5kIC1FIC8gLVggb3B0aW9ucyBhcmUgbXV0dWFsbHkgZXhjbHVzaXZlXG4iKTsKKyAgICAgICAg ICBleGl0KDEpOworICAgICAgICB9CiAgICAgICAgIGlmIChvcHQubnVtX2V4Y2wgPj0gb3B0Lm1h eF9leGNsKQogICAgICAgICB7CiAgICAgICAgICAgIG9wdC5tYXhfZXhjbCArPSAxNjsKQEAgLTEx ODUsNiArMTI3MiwyMSBAQCBzdGF0aWMgaW50IHdyaXRlX2R4ZShGSUxFICppbmYsIEZJTEUgKm91 CiAgICAgICAgICAgY29udGludWU7CiAgICAgICB9CiAKKyAgICAgIGlmIChvcHQubnVtX25hbWVz KQorICAgICAgeworICAgICAgICBCT09MIG9rID0gRkFMU0U7CisgICAgICAgIGZvciAoaiA9IDA7 IGogPCBvcHQubnVtX25hbWVzOyBqKyspCisgICAgICAgIHsKKyAgICAgICAgICBpZiAoc3RyY21w KG9wdC5leHBvcnRfbmFtZXNbal0sIG5hbWUpID09IDApCisgICAgICAgICAgeworICAgICAgICAg ICAgb2sgPSBUUlVFOworICAgICAgICAgICAgYnJlYWs7CisgICAgICAgICAgfQorICAgICAgICB9 CisgICAgICAgIGlmICghb2spCisgICAgICAgICAgY29udGludWU7CisgICAgICB9CisKICAgICAg IC8qIGV4cG9ydGVkIHN5bWJvbCAqLwogICAgICAgZGgubl9leHBfc3ltcysrOwogCg== --000000000000eaaa5a05f37e8882--