Re: [PATCH 09/13] parse-options API: don't restrict OPT_SUBCOMMAND() to one *_fn type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Đoàn

On 05/11/2022 11:34, Đoàn Trần Công Danh wrote:
On 2022-11-05 09:32:44+0100, René Scharfe <l.s.r@xxxxxx> wrote:
Why is this trickery needed?  Above you write that callbacks in
builtin/bisect--helper.c can't use subcommand_fn because they need
their own argument.  Can we extend subcommand_fn or use a global
variable to pass that extra thing instead?  The latter may be ugly, but
at least it's valid C..

Not the author, but I fully agree with you, I think instead of adding new API
for some arbitrary subcommand_fn, I would change the subcommand_fn to
type:

	int (*)(int argc, const char **argv, const char *prefix, void *context)

The last argument would be an object pointer, which will be casted to
the correct type inside the callback.

Let me cherry-picking this series on top of mine to see how things
would progress.

Unfortunately the current implementation of OPT_SUBCOMMAND relies on returning a function pointer though a void* variable which while widely supported is undefined behavior. I wonder if an API like

typedef int (*subcommand_fn)(int, char**, char*);
typedef int (*subcommand_ctk_fn)(int, char**, char*, void*);
struct subcommand; /* opaque */

OPT_SUBCOMMAND(name, value, func);
OPT_SUMCOMMAND_CTX(name, value, func, ctx);

int call_subcommand(struct subcommand* subcommand, int argc, char** argv, char* prefix);


which would be used as

int sub1_fn(int argc, char** argv, char* prefix, void* ctx)
{
	struct cmd_ctx cmd_ctx = ctx
	...
}

int sub2_fn(int argc, char** argv, char* prefix)
{
	...
}

int cmd_foo(int argc, char** argv, char* prefix)
{
	struct cmd_ctx ctx = ...
	struct subcommand cmd = { 0 };
	...
	struct option opts[] = {
		OPT_SUBCOMMAND_CTX("sub1", &cmd, sub_fn, &ctx);
		OPT_SUBCOMMAND("sub2", &cmd, sub2_fn);
	};
	argc = parse_options(argc, argv, prefix, &opts, usage, flags);
	return call_subcommand(&cmd, argc, argv, prefix);
}


would be an improvement. One can avoid having to mark the ctx parameter as UNUSED() if a subcommand does not need any context by using OPT_SUBCOMMAND() rather than OPT_SUBCOMMAND_CTX().


The implementation of call_subcommand() would look something like

struct subcommand {
        void* ctx;
        int has_ctx;
        union {
                subcommand_fn fn;
                subcommand_ctx_fn ctx_fn;
        };
};

int call_subcommand(struct subcommand* subcommand, int argc, char **argv, char* prefix)
{
        if (subcommand->has_ctx)
return subcommand->ctx_fn(argc, argv, prefix, subcommand->ctx);
        else
                return subcommand->fn(argc, argv, prefix);
}


Best Wishes

Phillip



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux