From c0e56edaf256adb6c60c5a052525a1ffbb927901 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 8 Oct 2012 00:02:30 -0500 Subject: New build infrastructure to generate FLAG_ macros and TT alias, #define FOR_commandname before #including toys.h to trigger it. Rename DEFINE_GLOBALS() to just GLOBALS() (because I could never remember if it was DECLARE_GLOBALS). Convert existing commands to use new infrastructure, and replace optflag constants with FLAG_ macros where appropriate. --- www/code.html | 114 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 37 deletions(-) (limited to 'www/code.html') diff --git a/www/code.html b/www/code.html index 3a77a3ce..73348ca0 100644 --- a/www/code.html +++ b/www/code.html @@ -74,7 +74,8 @@ multiple commands:
  • lib/dirtree.c
  • The toys directory contains the C files implementating -each command.
  • +each command. Currently it contains three subdirectories: +posix, lsb, and other.
  • The scripts directory contains the build and test infrastructure.
  • The kconfig directory contains the configuration @@ -85,13 +86,18 @@ files generated from other parts of the source code.
  • Adding a new command

    -

    To add a new command to toybox, add a C file implementing that command to +

    To add a new command to toybox, add a C file implementing that command under the toys directory. No other files need to be modified; the build extracts all the information it needs (such as command line arguments) from specially formatted comments and macros in the C file. (See the description of the "generated" directory for details.)

    -

    An easy way to start a new command is copy the file "hello.c" to +

    Currently there are three subdirectories under "toys", one for commands +defined by the POSIX standard, one for commands defined by the Linux Standard +Base, and one for all other commands. (This is just for developer convenience +sorting them, the directories are otherwise functionally identical.)

    + +

    An easy way to start a new command is copy the file "toys/other/hello.c" to the name of the new command, and modify this copy to implement the new command. This file is an example command meant to be used as a "skeleton" for new commands (more or less by turning every instance of "hello" into the @@ -104,7 +110,7 @@ variables that a "hello world" program doesn't strictly need).

    Here's a checklist of steps to turn hello.c into another command:

    Top level directory.

    @@ -178,7 +186,9 @@ happened to your command line arguments and how to access them.

    This directory contains global infrastructure.

    toys.h

    -

    Each command #includes "toys.h" as part of its standard prolog.

    +

    Each command #includes "toys.h" as part of its standard prolog. It +may "#define FOR_commandname" before doing so to get some extra entries +specific to this command.

    This file sucks in most of the commonly used standard #includes, so individual files can just #include "toys.h" and not have to worry about @@ -233,7 +243,7 @@ defining macros and #including generated/newtoys.h.

    command.

  • char *options - command line option string (used by get_optflags() in lib/args.c to intialize toys.optflags, toys.optargs, and -entries in the toy's DEFINE_GLOBALS struct). When this is NULL, no option +entries in the toy's GLOBALS struct). When this is NULL, no option parsing is done before calling toy_main().

  • int flags - Behavior flags for this command. The following flags are currently understood:

    @@ -269,7 +279,7 @@ unmodified string array passed in to main(). Note that modifying this changes "ps" output, and is not recommended. This array is null terminated; a NULL entry indicates the end of the array.

    Most commands don't use this field, instead the use optargs, optflags, -and the fields in the DEFINE_GLOBALS struct initialized by get_optflags().

    +and the fields in the GLOBALS struct initialized by get_optflags().

  • unsigned optflags - Command line option flags, set by get_optflags(). Indicates which of the command line options listed in @@ -282,8 +292,15 @@ the option string "abcd" would parse the command line "-c" to set optflags to 2, "-a" would set optflags to 8, and "-bd" would set optflags to 6 (4|2).

    Only letters are relevant to optflags. In the string "a*b:c#d", d=1, c=2, -b=4, a=8. The punctuation after a letter initializes global variables -(see [TODO] DECLARE_GLOBALS() for details).

    +b=4, a=8. Punctuation after a letter initializes global variables at the +start of the GLOBALS() block (see union toy_union this +for details).

    + +

    The build infrastructure creates FLAG_ macros for each option letter, +corresponding to the bit position, so you can check (toys.optflags & FLAG_x) +to see if a flag was specified. (The correct set of FLAG_ macros is selected +by defining FOR_mycommand before #including toys.h. The macros live in +toys/globals.h which is generated by scripts/make.sh.)

    For more information on option parsing, see get_optflags().

    @@ -299,6 +316,7 @@ via help_main() before exiting. (True during option parsing, defaults to false afterwards.)

  • +
  • union toy_union this - Union of structures containing each command's global variables.

    @@ -313,11 +331,12 @@ running would be wasteful.

    Toybox handles this by encapsulating each command's global variables in a structure, and declaring a union of those structures with a single global -instance (called "this"). The DEFINE_GLOBALS() macro contains the global +instance (called "this"). The GLOBALS() macro contains the global variables that should go in the current command's global structure. Each variable can then be accessed as "this.commandname.varname". -Generally, the macro TT is #defined to this.commandname so the variable -can then be accessed as "TT.variable". See toys/hello.c for an example.

    +If you #defined FOR_commandname before including toys.h, the macro TT is +#defined to this.commandname so the variable can then be accessed as +"TT.variable". See toys/hello.c for an example.

    A command that needs global variables should declare a structure to contain them all, and add that structure to this union. A command should never @@ -664,17 +683,16 @@ available to command_main():

    If the command's globals are:

    -DECLARE_GLOBALS(
    +GLOBALS(
     	char *c;
     	char *b;
     	long a;
     )
    -#define TT this.command
     

    That would mean TT.c == NULL, TT.b == "fruit", and TT.a == 42. (Remember, each entry that receives an argument must be a long or pointer, to line up with the array position. Right to left in the optflags string corresponds to -top to bottom in DECLARE_GLOBALS().

    +top to bottom in GLOBALS().

    long toys.optflags

    @@ -940,6 +958,28 @@ from elsewhere in the program. This gives ls -lR manual control of traversal order, which is neither depth first nor breadth first but instead a sort of FIFO order requried by the ls standard.

    +
    +

    Directory toys/

    + +

    This directory contains command implementations. Each command is a single +self-contained file. Adding a new command involves adding a single +file, and removing a command involves removing that file. Commands use +shared infrastructure from the lib/ and generated/ directories.

    + +

    Currently there are three subdirectories under "toys/" containing commands +described in POSIX-2008, the Linux Standard Base 4.1, or "other". The only +difference this makes is which menu the command shows up in during "make +menuconfig", the directories are otherwise identical. Note that they commands +exist within a single namespace at runtime, so you can't have the same +command in multiple subdirectories.

    + +

    (There are actually four sub-menus in "make menuconfig", the fourth +contains global configuration options for toybox, and lives in Config.in at +the top level.)

    + +

    See adding a new command for details on the +layout of a command file.

    +

    Directory scripts/

    scripts/cfg2files.sh

    -- cgit v1.2.3