Commit 1d7123d8 authored by Timo Teräs's avatar Timo Teräs

rewrite option descriptors to be single string

This reduces the number of relocations on PIE binaries, and also
reduces the executable size. Parsing of the options is slightly
sped up as only the exact matching option group parser is called.
parent 791f93fc
Pipeline #16986 passed with stage
in 38 seconds
This diff is collapsed.
......@@ -17,19 +17,17 @@
#include "apk_defines.h"
#include "apk_database.h"
struct apk_option {
int val;
const char *name;
int has_arg;
};
#define APK_OPTAPPLET "\x00"
#define APK_OPTGROUP(_name) _name "\x00"
#define APK_OPT1n(_opt) "\xf0" _opt "\x00"
#define APK_OPT1R(_opt) "\xaf" "\xf0" _opt "\x00"
#define APK_OPT2n(_opt, _short) _short _opt "\x00"
#define APK_OPT2R(_opt, _short) "\xaf" _short _opt "\x00"
struct apk_option_group {
const char *name;
int num_options;
const struct apk_option *options;
const char *desc;
int (*parse)(void *ctx, struct apk_db_options *dbopts,
int optch, const char *optarg);
int opt, const char *optarg);
};
struct apk_applet {
......
......@@ -23,24 +23,40 @@ struct add_ctx {
unsigned short extract_flags;
};
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_ADD_initdb,
OPT_ADD_latest,
OPT_ADD_no_chown,
OPT_ADD_upgrade,
OPT_ADD_virtual,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT1n("initdb")
APK_OPT2n("latest", "l")
APK_OPT1n("no-chown")
APK_OPT2n("upgrade", "u")
APK_OPT2R("virtual", "t");
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct add_ctx *actx = (struct add_ctx *) ctx;
switch (optch) {
case 0x10000:
switch (opt) {
case OPT_ADD_initdb:
dbopts->open_flags |= APK_OPENF_CREATE;
break;
case 0x10001:
case OPT_ADD_latest:
actx->solver_flags |= APK_SOLVERF_LATEST;
break;
case OPT_ADD_no_chown:
actx->extract_flags |= APK_EXTRACTF_NO_CHOWN;
break;
case 'u':
case OPT_ADD_upgrade:
actx->solver_flags |= APK_SOLVERF_UPGRADE;
break;
case 'l':
actx->solver_flags |= APK_SOLVERF_LATEST;
break;
case 't':
case OPT_ADD_virtual:
actx->virtpkg = optarg;
break;
default:
......@@ -49,18 +65,8 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt
return 0;
}
static const struct apk_option options_applet[] = {
{ 0x10000, "initdb" },
{ 0x10001, "no-chown" },
{ 'u', "upgrade" },
{ 'l', "latest" },
{ 't', "virtual", required_argument },
};
static const struct apk_option_group optgroup_applet = {
.name = "Add",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -37,24 +37,40 @@ struct audit_ctx {
unsigned packages_only : 1;
};
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_AUDIT_backup,
OPT_AUDIT_check_permissions,
OPT_AUDIT_packages,
OPT_AUDIT_recursive,
OPT_AUDIT_system,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT1n("backup")
APK_OPT1n("check-permissions")
APK_OPT1n("packages")
APK_OPT2n("recursive", "r")
APK_OPT1n("system");
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct audit_ctx *actx = (struct audit_ctx *) ctx;
switch (optch) {
case 0x10000:
switch (opt) {
case OPT_AUDIT_backup:
actx->mode = MODE_BACKUP;
break;
case 0x10001:
case OPT_AUDIT_system:
actx->mode = MODE_SYSTEM;
break;
case 0x10002:
case OPT_AUDIT_check_permissions:
actx->check_permissions = 1;
break;
case 0x10003:
case OPT_AUDIT_packages:
actx->packages_only = 1;
break;
case 'r':
case OPT_AUDIT_recursive:
actx->recursive = 1;
break;
default:
......@@ -63,18 +79,8 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt
return 0;
}
static const struct apk_option options_applet[] = {
{ 0x10000, "backup" },
{ 0x10001, "system" },
{ 0x10002, "check-permissions" },
{ 'r', "recursive" },
{ 0x10003, "packages" },
};
static const struct apk_option_group optgroup_applet = {
.name = "Audit",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -30,15 +30,25 @@ struct cache_ctx {
unsigned short solver_flags;
};
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_CACHE_latest,
OPT_CACHE_upgrade,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT2n("latest", "l")
APK_OPT2n("upgrade", "u");
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct cache_ctx *cctx = (struct cache_ctx *) ctx;
switch (optch) {
case 'u':
switch (opt) {
case OPT_CACHE_upgrade:
cctx->solver_flags |= APK_SOLVERF_UPGRADE;
break;
case 'l':
case OPT_CACHE_latest:
cctx->solver_flags |= APK_SOLVERF_LATEST;
break;
default:
......@@ -47,15 +57,8 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt
return 0;
}
static const struct apk_option options_applet[] = {
{ 'u', "upgrade" },
{ 'l', "latest" },
};
static const struct apk_option_group optgroup_applet = {
.name = "Cache",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -21,12 +21,20 @@ struct del_ctx {
int errors;
};
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_DEL_redepends,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT2n("rdepends", "r");
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct del_ctx *ctx = (struct del_ctx *) pctx;
switch (optch) {
case 'r':
switch (opt) {
case OPT_DEL_redepends:
ctx->recursive_delete = 1;
break;
default:
......@@ -35,14 +43,8 @@ static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int op
return 0;
}
static const struct apk_option options_applet[] = {
{ 'r', "rdepends" },
};
static const struct apk_option_group optgroup_applet = {
.name = "Delete",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -24,15 +24,25 @@ struct dot_ctx {
int installed_only : 1;
};
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_DOT_errors,
OPT_DOT_installed,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT1n("errors")
APK_OPT1n("installed");
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct dot_ctx *ctx = (struct dot_ctx *) pctx;
switch (optch) {
case 0x10000:
switch (opt) {
case OPT_DOT_errors:
ctx->errors_only = 1;
break;
case 0x10001:
case OPT_DOT_installed:
ctx->installed_only = 1;
dbopts->open_flags &= ~APK_OPENF_NO_INSTALLED;
break;
......@@ -42,15 +52,8 @@ static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int op
return 0;
}
static const struct apk_option options_applet[] = {
{ 0x10000, "errors" },
{ 0x10001, "installed" },
};
static const struct apk_option_group optgroup_applet = {
.name = "Dot",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -68,21 +68,40 @@ static int cup(void)
return write(STDOUT_FILENO, buf, len) != len;
}
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_FETCH_link,
OPT_FETCH_recursive,
OPT_FETCH_output,
OPT_FETCH_simulate,
OPT_FETCH_stdout,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT2n("link", "l")
APK_OPT2n("recursive", "R")
APK_OPT2R("output", "o")
APK_OPT1n("simulate")
APK_OPT2n("stdout", "s");
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct fetch_ctx *fctx = (struct fetch_ctx *) ctx;
switch (optch) {
case 'R':
switch (opt) {
case OPT_FETCH_simulate:
apk_flags |= APK_SIMULATE;
break;
case OPT_FETCH_recursive:
fctx->flags |= FETCH_RECURSIVE;
break;
case 's':
case OPT_FETCH_stdout:
fctx->flags |= FETCH_STDOUT;
break;
case 'L':
case OPT_FETCH_link:
fctx->flags |= FETCH_LINK;
break;
case 'o':
case OPT_FETCH_output:
fctx->outdir_fd = openat(AT_FDCWD, optarg, O_RDONLY | O_CLOEXEC);
break;
default:
......@@ -91,18 +110,8 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt
return 0;
}
static const struct apk_option options_applet[] = {
{ 'L', "link" },
{ 'R', "recursive" },
{ 0x104, "simulate" },
{ 's', "stdout" },
{ 'o', "output", required_argument },
};
static const struct apk_option_group optgroup_applet = {
.name = "Fetch",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -24,24 +24,40 @@ struct fix_ctx {
int errors;
};
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_FIX_depends,
OPT_FIX_directory_permissions,
OPT_FIX_reinstall,
OPT_FIX_upgrade,
OPT_FIX_xattr,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT2n("depends", "d")
APK_OPT1n("directory-permissions")
APK_OPT2n("reinstall", "r")
APK_OPT2n("upgrade", "u")
APK_OPT2n("xattr", "x");
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct fix_ctx *ctx = (struct fix_ctx *) pctx;
switch (optch) {
case 'd':
switch (opt) {
case OPT_FIX_depends:
ctx->fix_depends = 1;
break;
case 'x':
ctx->fix_xattrs = 1;
break;
case 'u':
ctx->solver_flags |= APK_SOLVERF_UPGRADE;
case OPT_FIX_directory_permissions:
ctx->fix_directory_permissions = 1;
break;
case 'r':
case OPT_FIX_reinstall:
ctx->solver_flags |= APK_SOLVERF_REINSTALL;
break;
case 0x10000:
ctx->fix_directory_permissions = 1;
case OPT_FIX_upgrade:
ctx->solver_flags |= APK_SOLVERF_UPGRADE;
break;
case OPT_FIX_xattr:
ctx->fix_xattrs = 1;
break;
default:
return -ENOTSUP;
......@@ -49,18 +65,8 @@ static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int op
return 0;
}
static const struct apk_option options_applet[] = {
{ 'd', "depends" },
{ 'r', "reinstall" },
{ 'u', "upgrade" },
{ 'x', "xattr" },
{ 0x10000, "directory-permissions" },
};
static const struct apk_option_group optgroup_applet = {
.name = "Fix",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -32,21 +32,35 @@ struct index_ctx {
int method;
};
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_INDEX_description,
OPT_INDEX_index,
OPT_INDEX_output,
OPT_INDEX_rewrite_arch,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT2R("description", "d")
APK_OPT2R("index", "x")
APK_OPT2R("output", "o")
APK_OPT1R("rewrite-arch");
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct index_ctx *ictx = (struct index_ctx *) ctx;
switch (optch) {
case 'x':
switch (opt) {
case OPT_INDEX_description:
ictx->description = optarg;
break;
case OPT_INDEX_index:
ictx->index = optarg;
break;
case 'o':
case OPT_INDEX_output:
ictx->output = optarg;
break;
case 'd':
ictx->description = optarg;
break;
case 0x10000:
case OPT_INDEX_rewrite_arch:
ictx->rewrite_arch = apk_blob_atomize(APK_BLOB_STR(optarg));
break;
default:
......@@ -55,17 +69,8 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt
return 0;
}
static const struct apk_option options_applet[] = {
{ 'o', "output", required_argument },
{ 'x', "index", required_argument },
{ 'd', "description", required_argument },
{ 0x10000, "rewrite-arch", required_argument },
};
static const struct apk_option_group optgroup_applet = {
.name = "Index",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -366,57 +366,93 @@ static void print_name_info(struct apk_database *db, const char *match, struct a
info_subaction(ctx, p->pkg);
}
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_INFO_all,
OPT_INFO_contents,
OPT_INFO_depends,
OPT_INFO_description,
OPT_INFO_install_if,
OPT_INFO_installed,
OPT_INFO_license,
OPT_INFO_provides,
OPT_INFO_rdepends,
OPT_INFO_replaces,
OPT_INFO_rinstall_if,
OPT_INFO_size,
OPT_INFO_triggers,
OPT_INFO_webpage,
OPT_INFO_who_owns,
};
static const char option_desc[] =
APK_OPTAPPLET
APK_OPT2n("all", "a")
APK_OPT2n("contents", "L")
APK_OPT2n("depends", "R")
APK_OPT2n("description", "d")
APK_OPT1n("install-if")
APK_OPT2n("installed", "e")
APK_OPT1n("license")
APK_OPT2n("provides", "P")
APK_OPT2n("rdepends", "r")
APK_OPT1n("replaces")
APK_OPT1n("rinstall-if")
APK_OPT2n("size", "s")
APK_OPT2n("triggers", "t")
APK_OPT2n("webpage", "w")
APK_OPT2n("who-owns", "W");
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg)
{
struct info_ctx *ctx = (struct info_ctx *) pctx;
ctx->action = NULL;
switch (optch) {
case 'e':
switch (opt) {
case OPT_INFO_installed:
ctx->action = info_exists;
dbopts->open_flags |= APK_OPENF_NO_REPOS;
break;
case 'W':
case OPT_INFO_who_owns:
ctx->action = info_who_owns;
dbopts->open_flags |= APK_OPENF_NO_REPOS;
break;
case 'w':
case OPT_INFO_webpage:
ctx->subaction_mask |= APK_INFO_URL;
break;
case 'R':
case OPT_INFO_depends:
ctx->subaction_mask |= APK_INFO_DEPENDS;
break;
case 'P':
case OPT_INFO_provides:
ctx->subaction_mask |= APK_INFO_PROVIDES;
break;
case 'r':
case OPT_INFO_rdepends:
ctx->subaction_mask |= APK_INFO_RDEPENDS;
break;
case 0x10002:
case OPT_INFO_install_if:
ctx->subaction_mask |= APK_INFO_INSTALL_IF;
break;
case 0x10003:
case OPT_INFO_rinstall_if:
ctx->subaction_mask |= APK_INFO_RINSTALL_IF;
break;
case 's':
case OPT_INFO_size:
ctx->subaction_mask |= APK_INFO_SIZE;
break;
case 'd':
case OPT_INFO_description:
ctx->subaction_mask |= APK_INFO_DESC;
break;
case 'L':
case OPT_INFO_contents:
ctx->subaction_mask |= APK_INFO_CONTENTS;
break;
case 't':
case OPT_INFO_triggers:
ctx->subaction_mask |= APK_INFO_TRIGGERS;
break;
case 0x10000:
case OPT_INFO_replaces:
ctx->subaction_mask |= APK_INFO_REPLACES;
break;
case 0x10001:
case OPT_INFO_license:
ctx->subaction_mask |= APK_INFO_LICENSE;
break;
case 'a':
case OPT_INFO_all:
ctx->subaction_mask = 0xffffffff;
break;
default:
......@@ -449,28 +485,8 @@ static int info_main(void *ctx, struct apk_database *db, struct apk_string_array
return ictx->errors;
}
static const struct apk_option options_applet[] = {
{ 'L', "contents" },
{ 'e', "installed" },
{ 'W', "who-owns" },
{ 'R', "depends" },
{ 'P', "provides" },
{ 'r', "rdepends" },
{ 0x10000, "replaces" },
{ 0x10002, "install-if" },
{ 0x10003, "rinstall-if" },
{ 'w', "webpage" },
{ 's', "size" },
{ 'd', "description" },
{ 0x10001, "license" },
{ 't', "triggers" },
{ 'a', "all" },
};
static const struct apk_option_group optgroup_applet = {
.name = "Info",
.options = options_applet,
.num_options = ARRAY_SIZE(options_applet),
.desc = option_desc,
.parse = option_parse_applet,
};
......
......@@ -187,38 +187,57 @@ static void print_result(struct apk_database *db, const char *match, struct apk_
iterate_providers(name, ctx);
}
static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg)
enum {
OPT_LIST_available,
OPT_LIST_installed,
OPT_LIST_depends,
OPT_LIST_origin,
OPT_LIST_orphaned,
OPT_LIST_providers,
OPT_LIST_upgradeable,