Add experimental (and undocumented) --help-verbose and --help-short options.

This commit is contained in:
Markus F.X.J. Oberhumer
2024-04-21 14:20:18 +02:00
parent eb3c55b5cb
commit 9d26713b1a
9 changed files with 105 additions and 49 deletions
+52 -14
View File
@@ -34,6 +34,7 @@ static constexpr long long initial_win32_winnt = 0;
#include "conf.h"
#include "compress/compress.h" // upx_ucl_version_string()
// for list_all_packers():
#include "filter.h" // Filter::isValidFilter
#include "packer.h"
#include "packmast.h" // PackMaster::visitAllPackers
@@ -101,48 +102,85 @@ void show_usage(void) {
namespace {
struct PackerNames final {
PackerNames() noexcept = default;
explicit PackerNames() noexcept = default;
~PackerNames() noexcept = default;
static constexpr size_t MAX_NAMES = 64;
static constexpr size_t MAX_METHODS = 8;
static constexpr size_t MAX_FILTERS = 16;
struct Entry {
const char *fname;
const char *sname;
size_t methods_count;
size_t filters_count;
unsigned methods[MAX_METHODS];
unsigned filters[MAX_FILTERS];
};
static constexpr size_t MAX_NAMES = 64;
Entry names[MAX_NAMES];
size_t names_count = 0;
const Options *o = nullptr;
void add(const PackerBase *pb) {
assert_noexcept(names_count < MAX_NAMES);
names[names_count].fname = pb->getFullName(o);
names[names_count].sname = pb->getName();
names_count++;
Entry &e = names[names_count++];
e.fname = pb->getFullName(o);
e.sname = pb->getName();
e.methods_count = e.filters_count = 0;
for (const int *m = pb->getCompressionMethods(M_ALL, 10); *m != M_END; m++) {
if (*m >= 0) {
assert_noexcept(Packer::isValidCompressionMethod(*m));
assert_noexcept(e.methods_count < MAX_METHODS);
e.methods[e.methods_count++] = *m;
}
}
for (const int *f = pb->getFilters(); f != nullptr && *f != FT_END; f++) {
if (*f >= 0) {
assert_noexcept(Filter::isValidFilter(*f));
assert_noexcept(e.filters_count < MAX_FILTERS);
e.filters[e.filters_count++] = *f;
}
}
upx_gnomesort(e.methods, e.methods_count, sizeof(e.methods[0]), ne32_compare);
upx_gnomesort(e.filters, e.filters_count, sizeof(e.filters[0]), ne32_compare);
}
static tribool visit(PackerBase *pb, void *user) {
NO_fprintf(stderr, "visit %s\n", pb->getFullName(nullptr));
PackerNames *self = (PackerNames *) user;
self->add(pb);
return false;
}
static int __acc_cdecl_qsort cmp_fname(const void *a, const void *b) {
static int __acc_cdecl_qsort compare_fname(const void *a, const void *b) {
return strcmp(((const Entry *) a)->fname, ((const Entry *) b)->fname);
}
static int __acc_cdecl_qsort cmp_sname(const void *a, const void *b) {
static int __acc_cdecl_qsort compare_sname(const void *a, const void *b) {
return strcmp(((const Entry *) a)->sname, ((const Entry *) b)->sname);
}
};
} // namespace
static void list_all_packers(FILE *f, int verbose) {
static noinline void list_all_packers(FILE *f, int verbose) {
Options o;
o.reset();
PackerNames pn;
pn.o = &o;
(void) PackMaster::visitAllPackers(PackerNames::visit, nullptr, &o, &pn);
upx_qsort(pn.names, pn.names_count, sizeof(PackerNames::Entry), PackerNames::cmp_fname);
upx_gnomesort(pn.names, pn.names_count, sizeof(PackerNames::Entry), PackerNames::compare_fname);
size_t pos = 0;
for (size_t i = 0; i < pn.names_count; ++i) {
const char *fn = pn.names[i].fname;
const char *sn = pn.names[i].sname;
if (verbose > 0) {
for (size_t i = 0; i < pn.names_count; i++) {
const PackerNames::Entry &e = pn.names[i];
const char *const fn = e.fname;
const char *const sn = e.sname;
if (verbose >= 3) {
con_fprintf(f, " %-36s %s\n", fn, sn);
con_fprintf(f, " methods:");
for (size_t j = 0; j < e.methods_count; j++)
con_fprintf(f, " %#x", e.methods[j]);
con_fprintf(f, "\n");
con_fprintf(f, " filters:");
for (size_t j = 0; j < e.filters_count; j++)
con_fprintf(f, " %#x", e.filters[j]);
con_fprintf(f, "\n");
} else if (verbose >= 2) {
con_fprintf(f, " %-36s %s\n", fn, sn);
} else {
size_t fl = strlen(fn);
@@ -158,7 +196,7 @@ static void list_all_packers(FILE *f, int verbose) {
}
}
}
if (verbose <= 0 && pn.names_count)
if (verbose < 2 && pn.names_count)
con_fprintf(f, "\n");
}