Attached is an extended version of hello.c showing how to implement multiple commands with different arguments in the same file. (This allows them to share infrastructure that doesn't live in lib/lib.c.)
To switch from one command to another, you do this: #define CLEANUP_oldcommand #define FOR_newcommand #include "generated/flags.h" Most of the infrastructure was already in place, the recent fixes were things like not undefining TT and redefining it (which didn't work). Instead, you need to put a union at the start of GLOBALS with the variables the command line option parsing logic populates, and then the other global variables after that. That way the layout's correct for the commands, and both their FLAG_ and TT. values are usable from both contexts. (You have to use the union name to access the variables, but oh well.) Plus a lot of header generation fixes... I needed this for gzip/zlib/zip to share deflate code without putting it in /lib. (Tar can fork and pipe data through gzip, as is the unix way.) I've also moved bunzip2 out of lib and into the command using it: bzcat and bunzip2 aren't enough reason to slow down every single command build. Especially with scripts/single.sh builds, significant extra lib code is noticeable. I've decided _not_ to complicate hello.c with the extra plumbing, it's complicated enough as it is, but here's how it would look if I did. I should add this to the documentation. Rob
/* hello.c - A hello world program. (Template for new commands.) * * Copyright 2012 Rob Landley <[email protected]> * * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html // Accept many different kinds of command line argument: USE_HELLO(NEWTOY(hello, "(walrus)(blubber):;(also):e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN)) USE_HELLO_ALIAS(NEWTOY(hello_alias, "b:dq", TOYFLAG_USR|TOYFLAG_BIN)) config HELLO bool "hello" default n help usage: hello [-a] [-b STRING] [-c NUMBER] [-d LIST] [-e COUNT] [...] A hello world program. You don't need this. Mostly used as an example/skeleton file for adding new commands, occasionally nice to test kernel booting via "init=/bin/hello". config HELLO_ALIAS bool "hello_alias" default n depends on HELLO help usage: hello_alias [-dq] [-b NUMBER] Example of a second command with different arguments in the same source file as the first. Allows shared infrastructure not added to lib. */ #define FOR_hello #include "toys.h" // Hello doesn't use these globals, they're here for example/skeleton purposes. GLOBALS( union { struct { char *b_string; long c_number; struct arg_list *d_list; long e_count; char *also_string; char *blubber_string; } h; struct { long b_number; } a; }; int more_globals; ) // Parse many different kinds of command line argument: void hello_main(void) { char **optargs; printf("Hello world\n"); if (toys.optflags) printf("flags=%x\n", toys.optflags); if (toys.optflags & FLAG_a) printf("Saw a\n"); if (toys.optflags & FLAG_b) printf("b=%s\n", TT.h.b_string); if (toys.optflags & FLAG_c) printf("c=%ld\n", TT.h.c_number); while (TT.h.d_list) { printf("d=%s\n", TT.h.d_list->arg); TT.h.d_list = TT.h.d_list->next; } if (TT.h.e_count) printf("e was seen %ld times\n", TT.h.e_count); for (optargs = toys.optargs; *optargs; optargs++) printf("optarg=%s\n", *optargs); if (toys.optflags & FLAG_walrus) printf("Saw --walrus\n"); if (TT.h.blubber_string) printf("--blubber=%s\n", TT.h.blubber_string); } #define CLEANUP_hello #define FOR_hello_alias #include "generated/flags.h" void hello_alias_main(void) { printf("hello world %x\n", toys.optflags); if (toys.optflags & FLAG_b) printf("b=%ld", TT.a.b_number); }
_______________________________________________ Toybox mailing list [email protected] http://lists.landley.net/listinfo.cgi/toybox-landley.net
