changeset 674:7e846e281e38

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.
author Rob Landley <rob@landley.net>
date Mon, 08 Oct 2012 00:02:30 -0500
parents c102f31a753e
children fa858a67e231
files scripts/make.sh toys.h toys/lsb/dmesg.c toys/lsb/hostname.c toys/lsb/killall.c toys/lsb/mknod.c toys/lsb/mktemp.c toys/lsb/passwd.c toys/other/catv.c toys/other/dos2unix.c toys/other/free.c toys/other/hello.c toys/other/login.c toys/other/mke2fs.c toys/other/modinfo.c toys/other/mountpoint.c toys/other/netcat.c toys/other/oneit.c toys/other/rmmod.c toys/other/sha1sum.c toys/other/swapon.c toys/other/switch_root.c toys/other/taskset.c toys/other/truncate.c toys/other/vmstat.c toys/posix/chgrp.c toys/posix/chmod.c toys/posix/cksum.c toys/posix/cmp.c toys/posix/comm.c toys/posix/cp.c toys/posix/date.c toys/posix/df.c toys/posix/du.c toys/posix/echo.c toys/posix/env.c toys/posix/head.c toys/posix/id.c toys/posix/kill.c toys/posix/ln.c toys/posix/ls.c toys/posix/mkdir.c toys/posix/mkfifo.c toys/posix/nice.c toys/posix/od.c toys/posix/patch.c toys/posix/sed.c toys/posix/sh.c toys/posix/sort.c toys/posix/tail.c toys/posix/tee.c toys/posix/uname.c toys/posix/uniq.c toys/posix/wc.c toys/posix/xargs.c www/code.html
diffstat 56 files changed, 322 insertions(+), 462 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/make.sh	Sun Oct 07 23:53:25 2012 -0500
+++ b/scripts/make.sh	Mon Oct 08 00:02:30 2012 -0500
@@ -10,81 +10,6 @@
   exit 1
 fi
 
-echo "Extract configuration information from toys/*.c files..."
-scripts/genconfig.sh
-
-echo "Generate headers from toys/*/*.c..."
-
-# Create a list of all the applets toybox can provide.  Note that the first
-# entry is out of order on purpose (the toybox multiplexer applet must be the
-# first element of the array).  The rest must be sorted in alphabetical order
-# for fast binary search.
-
-echo "generated/newtoys.h"
-
-function newtoys()
-{
-  for i in toys/*/*.c
-  do
-    sed -n -e '1,/^config [A-Z]/s/^USE_/&/p' $i || exit 1
-  done
-}
-echo "NEWTOY(toybox, NULL, TOYFLAG_STAYROOT)" > generated/newtoys.h
-newtoys | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \
-	| sed 's/[^ ]* //'  >> generated/newtoys.h
-
-# Extract global structure definitions and flag definitions from toys/*/*.c
-
-function getglobals()
-{
-  for i in toys/*/*.c
-  do
-    NAME="$(echo $i | sed 's@.*/\(.*\)\.c@\1@')"
-
-    echo -e "// $i\n"
-    sed -n -e '/^DEFINE_GLOBALS(/,/^)/b got;b;:got' \
-        -e 's/^DEFINE_GLOBALS(/struct '"$NAME"'_data {/' \
-        -e 's/^)/};/' -e 'p' $i
-
-    # And get flag definitions
-    FLAGS="$(sed -n \
-                 -e "s/.*TOY($NAME"',[ \t]*"\([^"]*\)"[ \t]*,.*)/\1/' \
-                 -e 't keep;d;:keep' \
-                 -e 's/[><=][0-9][0-9]*//g' \
-                 -e 's/+.//g' \
-                 -e 's/([^)]*)//g' \
-                 -e 's/[-?^:&#|@*]//g' \
-                 -e 'p' \
-                 generated/newtoys.h)"
-    X=0
-    while [ $X -lt ${#FLAGS} ]
-    do
-      echo -ne "#define OPTFLAG_${NAME}_${FLAGS:$X:1}\t"
-      X=$(($X+1))
-      echo "(1<<$((${#FLAGS}-$X)))"
-    done
-  done
-}
-
-echo "generated/globals.h"
-
-GLOBSTRUCT="$(getglobals)"
-(
-  echo "$GLOBSTRUCT"
-  echo
-  echo "extern union global_union {"
-  echo "$GLOBSTRUCT" | sed -n 's/struct \(.*\)_data {/	struct \1_data \1;/p'
-  echo "} this;"
-) > generated/globals.h
-
-echo "generated/help.h"
-# Only recreate generated/help.h if python is installed
-if [ ! -z "$(which python)" ] && [ ! -z "$(grep 'CONFIG_HELP=y' .config)" ]
-then
-  echo "Extract help text from Config.in."
-  scripts/config2help.py Config.in > generated/help.h || exit 1
-fi
-
 echo "Make generated/config.h from .config."
 
 # This long and roundabout sed invocation is to make old versions of sed happy.
@@ -111,6 +36,76 @@
   -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \
   .config > generated/config.h || exit 1
 
+
+echo "Extract configuration information from toys/*.c files..."
+scripts/genconfig.sh
+
+echo "Generate headers from toys/*/*.c..."
+
+# Create a list of all the applets toybox can provide.  Note that the first
+# entry is out of order on purpose (the toybox multiplexer applet must be the
+# first element of the array).  The rest must be sorted in alphabetical order
+# for fast binary search.
+
+echo "generated/newtoys.h"
+
+echo "NEWTOY(toybox, NULL, TOYFLAG_STAYROOT)" > generated/newtoys.h
+sed -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \
+	| sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \
+	| sed 's/[^ ]* //'  >> generated/newtoys.h
+
+# Extract global structure definitions and flag definitions from toys/*/*.c
+
+function getglobals()
+{
+  NEWTOYS="$(cat generated/config.h generated/newtoys.h | gcc -E - | sed 's/" *"//g')"
+  for i in toys/*/*.c
+  do
+    NAME="$(echo $i | sed 's@.*/\(.*\)\.c@\1@')"
+
+    echo -e "// $i\n"
+    sed -n -e '/^GLOBALS(/,/^)/b got;b;:got' \
+        -e 's/^GLOBALS(/struct '"$NAME"'_data {/' \
+        -e 's/^)/};/' -e 'p' $i
+
+    # And get flag definitions
+    FLAGS="$(echo "$NEWTOYS" | sed -n \
+                 -e "s/.*TOY($NAME"',[ \t]*"\([^"]*\)"[ \t]*,.*)/\1/' \
+                 -e 't keep;d;:keep' -e 's/^[<>=][0-9]//' -e 's/[?&^]//' \
+                 -e 't keep' -e 's/[><=][0-9][0-9]*//g' -e 's/+.//g' \
+                 -e 's/([^)]*)//g' -e 's/[-?^:&#|@*]//g' -e 'p')"
+    echo "#ifdef FOR_${NAME}"
+    X=0
+    while [ $X -lt ${#FLAGS} ]
+    do
+      echo -ne "#define FLAG_${FLAGS:$X:1}\t"
+      X=$(($X+1))
+      echo "(1<<$((${#FLAGS}-$X)))"
+    done
+    echo "#define TT this.${NAME}"
+    echo "#endif"
+  done
+}
+
+echo "generated/globals.h"
+
+GLOBSTRUCT="$(getglobals)"
+(
+  echo "$GLOBSTRUCT"
+  echo
+  echo "extern union global_union {"
+  echo "$GLOBSTRUCT" | sed -n 's/struct \(.*\)_data {/	struct \1_data \1;/p'
+  echo "} this;"
+) > generated/globals.h
+
+echo "generated/help.h"
+# Only recreate generated/help.h if python is installed
+if [ ! -z "$(which python)" ] && [ ! -z "$(grep 'CONFIG_HELP=y' .config)" ]
+then
+  echo "Extract help text from Config.in."
+  scripts/config2help.py Config.in > generated/help.h || exit 1
+fi
+
 # Extract a list of toys/*/*.c files to compile from the data in ".config":
 
 # 1) Get a list of C files in toys/* and glue them together into a regex we can
--- a/toys.h	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys.h	Mon Oct 08 00:02:30 2012 -0500
@@ -107,6 +107,6 @@
 
 extern char toybuf[4096];
 
-#define DEFINE_GLOBALS(...)
+#define GLOBALS(...)
 
 #define ARRAY_LEN(array) (sizeof(array)/sizeof(*array))
--- a/toys/lsb/dmesg.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/lsb/dmesg.c	Mon Oct 08 00:02:30 2012 -0500
@@ -21,16 +21,15 @@
 	  -c	Clear the ring buffer after printing.
 */
 
+#define FOR_dmesg
 #include "toys.h"
 #include <sys/klog.h>
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long level;
 	long size;
 )
 
-#define TT this.dmesg
-
 void dmesg_main(void)
 {
 	// For -n just tell kernel to which messages to keep.
--- a/toys/lsb/hostname.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/lsb/hostname.c	Mon Oct 08 00:02:30 2012 -0500
@@ -17,6 +17,7 @@
 	  Get/Set the current hostname
 */
 
+#define FOR_hostname
 #include "toys.h"
 
 void hostname_main(void)
--- a/toys/lsb/killall.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/lsb/killall.c	Mon Oct 08 00:02:30 2012 -0500
@@ -20,15 +20,12 @@
 		-q	don't print any warnings or error messages
 */
 
+#define FOR_killall
 #include "toys.h"
 
-#define FLAG_q	1
-#define FLAG_l	2
-
-DEFINE_GLOBALS(
+GLOBALS(
 	int signum;
 )
-#define TT this.killall
 
 static void kill_process(pid_t pid)
 {
--- a/toys/lsb/mknod.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/lsb/mknod.c	Mon Oct 08 00:02:30 2012 -0500
@@ -20,6 +20,7 @@
 	  p	named pipe (ignores MAJOR/MINOR)
 */
 
+#define FOR_mknod
 #include "toys.h"
 
 void mknod_main(void)
--- a/toys/lsb/mktemp.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/lsb/mktemp.c	Mon Oct 08 00:02:30 2012 -0500
@@ -22,18 +22,13 @@
 	  -q                     Quiet
 */
 
+#define FOR_mktemp
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char * tmpdir;
 )
 
-#define FLAG_p 1
-#define FLAG_d 2
-#define FLAG_q 4
-
-#define TT this.mktemp
-
 void mktemp_main(void)
 {
 	int  d_flag = toys.optflags & FLAG_d;
--- a/toys/lsb/passwd.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/lsb/passwd.c	Mon Oct 08 00:02:30 2012 -0500
@@ -24,21 +24,14 @@
 
 */
 
+#define FOR_passwd
 #include "toys.h"
 #include <time.h>
 
-
-DEFINE_GLOBALS(
+GLOBALS(
 	char *algo;
 )
 
-#define TT this.passwd
-
-#define FLAG_u	(1 << 0)
-#define FLAG_l	(1 << 1)
-#define FLAG_d	(1 << 2)
-#define FLAG_a	(1 << 3)
-
 #define MAX_SALT_LEN  20 //3 for id, 16 for key, 1 for '\0'
 #define URANDOM_PATH    "/dev/urandom"
 
--- a/toys/other/catv.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/catv.c	Mon Oct 08 00:02:30 2012 -0500
@@ -23,12 +23,9 @@
 	  -v	Don't use ^x or M-x escapes.
 */
 
+#define FOR_catv
 #include "toys.h"
 
-#define FLAG_v 4
-#define FLAG_t 2
-#define FLAG_e 1
-
 // Callback function for loopfiles()
 
 static void do_catv(int fd, char *name)
--- a/toys/other/dos2unix.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/dos2unix.c	Mon Oct 08 00:02:30 2012 -0500
@@ -17,14 +17,13 @@
 	  If no files listed copy from stdin, "-" is a synonym for stdin.
 */
 
+#define FOR_dos2unix
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *tempfile;
 )
 
-#define TT this.dos2unix
-
 static void do_dos2unix(int fd, char *name)
 {
 	char c = toys.which->name[0];
--- a/toys/other/free.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/free.c	Mon Oct 08 00:02:30 2012 -0500
@@ -18,6 +18,7 @@
 	  -bkmg    Output in bytes (default), KB, MB or GB
 */
 
+#define FOR_free
 #include "toys.h"
 
 static unsigned long long convert(unsigned long d, unsigned int iscale,
@@ -34,10 +35,10 @@
 
 	sysinfo(&info);
 	if (info.mem_unit) iscale = info.mem_unit;
-	if (toys.optflags & 1) oscale = 0;
-	if (toys.optflags & 2) oscale = 10;
-	if (toys.optflags & 4) oscale = 20;
-	if (toys.optflags & 8) oscale = 30;
+	if (toys.optflags & FLAG_b) oscale = 0;
+	if (toys.optflags & FLAG_k) oscale = 10;
+	if (toys.optflags & FLAG_m) oscale = 20;
+	if (toys.optflags & FLAG_g) oscale = 30;
 
 	xprintf("\t\ttotal        used        free      shared     buffers\n");
 	xprintf("Mem:%17llu%12llu%12llu%12llu%12llu\n",
--- a/toys/other/hello.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/hello.c	Mon Oct 08 00:02:30 2012 -0500
@@ -21,11 +21,12 @@
 	  occasionally nice to test kernel booting via "init=/bin/hello".
 */
 
+#define FOR_hello
 #include "toys.h"
 
 // Hello doesn't use these globals, they're here for example/skeleton purposes.
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *b_string;
 	long c_number;
 	struct arg_list *d_list;
@@ -34,14 +35,6 @@
 	int more_globals;
 )
 
-#define TT this.hello
-
-#define FLAG_a	1
-#define FLAG_b	2
-#define FLAG_c	4
-#define FLAG_d	8
-#define FLAG_e	16
-
 void hello_main(void)
 {
 	printf("Hello world\n");
--- a/toys/other/login.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/login.c	Mon Oct 08 00:02:30 2012 -0500
@@ -21,6 +21,7 @@
 	  -f    Do not perform authentication
 */
 
+#define FOR_login
 #include "toys.h"
 
 #define LOGIN_TIMEOUT 60
@@ -28,10 +29,9 @@
 #define USER_NAME_MAX_SIZE 32
 #define HOSTNAME_SIZE 32
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *hostname;
 )
-#define TT this.login
 
 static void login_timeout_handler(int sig __attribute__((unused)))
 {
@@ -162,9 +162,8 @@
 
 void login_main(void)
 {
-	int f_flag = (toys.optflags & 4) >> 2;
-	int p_flag = (toys.optflags & 2) >> 1;
-	int h_flag = toys.optflags & 1;
+	int f_flag = toys.optflags & FLAG_f;
+	int h_flag = toys.optflags & FLAG_h;
 	char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss;
 	struct passwd * pwd = NULL;
 	struct spwd * spwd = NULL;
@@ -215,7 +214,7 @@
 
 		f_flag = 0;
 		syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username,
-			ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:"");
+			ttyname(0), h_flag?"from":"", h_flag?TT.hostname:"");
 
 		sleep(LOGIN_FAIL_TIMEOUT);
 		puts("Login incorrect");
@@ -234,12 +233,12 @@
 
 	if (change_identity(pwd)) error_exit("Failed to change identity");
 
-	setup_environment(pwd, !p_flag);
+	setup_environment(pwd, !(toys.optflags & FLAG_p));
 
 	handle_motd();
 
 	syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name,
-		ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:"");
+		ttyname(0), h_flag?"from":"", h_flag?TT.hostname:"");
 
 	spawn_shell(pwd->pw_shell);
 }
--- a/toys/other/mke2fs.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/mke2fs.c	Mon Oct 08 00:02:30 2012 -0500
@@ -73,9 +73,10 @@
 	     sparse_super Don't allocate huge numbers of redundant superblocks
 */
 
+#define FOR_mke2fs
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	// Command line arguments.
 	long blocksize;
 	long bytes_per_inode;
@@ -102,9 +103,6 @@
 	struct ext2_superblock sb;
 )
 
-// Shortcut to our global data structure, since we use it so much.
-#define TT this.mke2fs
-
 #define INODES_RESERVED 10
 
 static uint32_t div_round_up(uint32_t a, uint32_t b)
--- a/toys/other/modinfo.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/modinfo.c	Mon Oct 08 00:02:30 2012 -0500
@@ -14,14 +14,12 @@
 	  usage: modinfo [-0] [-F field] [modulename...]
 */
 
+#define FOR_modinfo
 #include "toys.h"
 
-#define FLAG_0  (1 << 0)
-
-DEFINE_GLOBALS(
+GLOBALS(
     char *field;
 )
-#define TT this.modinfo
 
 static const char *modinfo_tags[] = {
     "alias", "license", "description", "author", "vermagic",
--- a/toys/other/mountpoint.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/mountpoint.c	Mon Oct 08 00:02:30 2012 -0500
@@ -17,19 +17,20 @@
 	  -x Print major/minor device number of the block device
 */
 
+#define FOR_mountpoint
 #include "toys.h"
 
 void mountpoint_main(void)
 {
 	struct stat st1, st2;
 	int res = 0;
-	int quiet = toys.optflags & 0x4;
+	int quiet = toys.optflags & FLAG_q;
 	toys.exitval = 1; // be pessimistic
 	strncpy(toybuf, toys.optargs[0], sizeof(toybuf));
-	if (((toys.optflags & 0x1) && lstat(toybuf, &st1)) || stat(toybuf, &st1))
+	if (((toys.optflags & FLAG_x) && lstat(toybuf, &st1)) || stat(toybuf, &st1))
 		perror_exit("%s", toybuf);
 
-	if (toys.optflags & 0x1){
+	if (toys.optflags & FLAG_x){
 		if (S_ISBLK(st1.st_mode)) {
 			if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev));
 			toys.exitval = 0;
@@ -48,7 +49,7 @@
 	res = (st1.st_dev != st2.st_dev) ||
 		(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
 	if (!quiet) printf("%s is %sa mountpoint\n", toys.optargs[0], res ? "" : "not ");
-	if (toys.optflags & 0x2)
+	if (toys.optflags & FLAG_d)
 		printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev));
 	toys.exitval = res ? 0 : 1;
 }
--- a/toys/other/netcat.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/netcat.c	Mon Oct 08 00:02:30 2012 -0500
@@ -3,6 +3,9 @@
  * netcat.c - Forward stdin/stdout to a file or network connection.
  *
  * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * TODO: udp, ipv6, genericize for telnet/microcom/tail-f
+
 
 USE_NETCAT(OLDTOY(nc, netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN))
 USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN))
@@ -40,10 +43,11 @@
 		netcat -s 127.0.0.1 -p 1234 -tL /bin/bash -l
 */
 
+#define FOR_netcat
 #include "toys.h"
 #include "toynet.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *filename;        // -f read from filename instead of network
 	long quit_delay;       // -q Exit after EOF from stdin after # seconds.
 	char *source_address;  // -s Bind to a specific source address.
@@ -51,13 +55,6 @@
 	long wait;             // -w Wait # seconds for a connection.
 )
 
-#define TT this.netcat
-
-#define FLAG_f   1
-#define FLAG_L  32
-#define FLAG_l  64
-#define FLAG_t 128
-
 static void timeout(int signum)
 {
 	if (TT.wait) error_exit("Timeout");
--- a/toys/other/oneit.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/oneit.c	Mon Oct 08 00:02:30 2012 -0500
@@ -24,15 +24,14 @@
 	  which point it reboots (or with -p, powers off) the system.
 */
 
+#define FOR_oneit
 #include "toys.h"
 #include <sys/reboot.h>
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *console;
 )
 
-#define TT this.oneit
-
 // The minimum amount of work necessary to get ctrl-c and such to work is:
 //
 // - Fork a child (PID 1 is special: can't exit, has various signals blocked).
@@ -59,7 +58,8 @@
 
 	// PID 1 can't call reboot() because it kills the task that calls it,
 	// which causes the kernel to panic before the actual reboot happens.
-	if (!vfork()) reboot((toys.optflags&1) ? RB_POWER_OFF : RB_AUTOBOOT);
+	if (!vfork())
+            reboot((toys.optflags & FLAG_p) ? RB_POWER_OFF : RB_AUTOBOOT);
 	sleep(5);
 	_exit(1);
   }
--- a/toys/other/rmmod.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/rmmod.c	Mon Oct 08 00:02:30 2012 -0500
@@ -18,6 +18,7 @@
 
 */
 
+#define FOR_rmmod
 #include "toys.h"
 
 #include <sys/syscall.h>
@@ -41,8 +42,8 @@
 	if (len > 3 && !strcmp(&mod_name[len-3], ".ko" ))
 		mod_name[len-3] = 0;
 
-	if (toys.optflags & 1) flags |= O_TRUNC;
-	if (toys.optflags & 2) flags &= ~O_NONBLOCK;
+	if (toys.optflags & FLAG_f) flags |= O_TRUNC;
+	if (toys.optflags & FLAG_w) flags &= ~O_NONBLOCK;
 
 	if (delete_module(mod_name, flags))
 		perror_exit("failed to unload %s", mod_name);
--- a/toys/other/sha1sum.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/sha1sum.c	Mon Oct 08 00:02:30 2012 -0500
@@ -18,9 +18,10 @@
 	  Calculate sha1 hash of files (or stdin).
 */
 
+#define FOR_sha1sum
 #include <toys.h>
 
-DEFINE_GLOBALS(
+GLOBALS(
 	uint32_t state[5];
 	uint32_t oldstate[5];
 	uint64_t count;
@@ -30,8 +31,6 @@
 	} buffer;
 )
 
-#define TT this.sha1sum
-
 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
 
 // blk0() and blk() perform the initial expand.
--- a/toys/other/swapon.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/swapon.c	Mon Oct 08 00:02:30 2012 -0500
@@ -15,19 +15,18 @@
 	  Enable swapping on a given device/file.
 */
 
+#define FOR_swapon
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long priority;
 )
 
-#define TT this.swapon
-
 void swapon_main(void)
 {
 	int flags = 0;
 
-	if (toys.optflags & 1)
+	if (toys.optflags)
 		flags = SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT);
 
 	if (swapon(*toys.optargs, flags))
--- a/toys/other/switch_root.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/switch_root.c	Mon Oct 08 00:02:30 2012 -0500
@@ -17,20 +17,16 @@
 	  -h	Hang instead of exiting on failure (avoids kernel panic)
 */
 
+#define FOR_switch_root
 #include "toys.h"
 #include <sys/vfs.h>
 
-DEFINE_GLOBALS(
+GLOBALS(
    char *console;
 
    dev_t rootdev;
 )
 
-#define TT this.switch_root
-
-#define FLAG_h  (1<<0)
-#define FLAG_c	(1<<1)
-
 static int del_node(struct dirtree *node)
 {
    if (node->st.st_dev == TT.rootdev && dirtree_notdotdot(node)) {
--- a/toys/other/taskset.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/taskset.c	Mon Oct 08 00:02:30 2012 -0500
@@ -22,11 +22,9 @@
 	  -a	Set/get the affinity of all threads of the PID.
 */
 
+#define FOR_taskset
 #include "toys.h"
 
-#define FLAG_a 0x1
-#define FLAG_p 0x2
-
 // Prototype for syscall wrappers sched.h refuses to give us
 int sched_setaffinity(pid_t pid, size_t size, void *cpuset);
 int sched_getaffinity(pid_t pid, size_t size, void *cpuset);
--- a/toys/other/truncate.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/truncate.c	Mon Oct 08 00:02:30 2012 -0500
@@ -17,14 +17,13 @@
 	  -s	New size
 */
 
+#define FOR_truncate
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long size;
 )
 
-#define TT this.truncate
-
 static void do_truncate(int fd, char *name)
 {
 	if (fd<0) return;
--- a/toys/other/vmstat.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/other/vmstat.c	Mon Oct 08 00:02:30 2012 -0500
@@ -122,7 +122,7 @@
 	unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2];
 	uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2];
 	int first_run = 1;
-	int no_header = toys.optflags & 0x1;
+	int no_header = toys.optflags;
 	unsigned num_rows = 22;
 
 	if (toys.optc >= 1)
--- a/toys/posix/chgrp.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/chgrp.c	Mon Oct 08 00:02:30 2012 -0500
@@ -30,25 +30,16 @@
 	  -v	verbose output.
 */
 
+#define FOR_chgrp
 #include "toys.h"
 
-#define FLAG_v 1
-#define FLAG_f 2
-#define FLAG_R 4
-#define FLAG_H 8
-#define FLAG_L 16
-#define FLAG_P 32
-#define FLAG_h 64
-
-DEFINE_GLOBALS(
+GLOBALS(
 	uid_t owner;
 	gid_t group;
 	char *owner_name, *group_name;
 	int symfollow;
 )
 
-#define TT this.chgrp
-
 static int do_chgrp(struct dirtree *node)
 {
 	int fd, ret, flags = toys.optflags;
--- a/toys/posix/chmod.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/chmod.c	Mon Oct 08 00:02:30 2012 -0500
@@ -34,17 +34,13 @@
         chmod 744 file - user can read/write/execute, everyone else read only
 */
 
+#define FOR_chmod
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
     char *mode;
 )
 
-#define TT this.chmod
-
-#define FLAG_R 1
-#define FLAG_v 2
-
 int do_chmod(struct dirtree *try)
 {
     mode_t mode;
--- a/toys/posix/cksum.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/cksum.c	Mon Oct 08 00:02:30 2012 -0500
@@ -23,14 +23,13 @@
 	  -N	Do not include length in CRC calculation
 */
 
+#define FOR_cksum
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	unsigned crc_table[256];
 )
 
-#define TT this.cksum
-
 static unsigned cksum_be(unsigned crc, unsigned char c)
 {
 	return (crc<<8)^TT.crc_table[(crc>>24)^c];
--- a/toys/posix/cmp.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/cmp.c	Mon Oct 08 00:02:30 2012 -0500
@@ -20,18 +20,14 @@
 	  -s silent
 */
 
+#define FOR_cmp
 #include "toys.h"
 
-#define FLAG_s	1
-#define FLAG_l	2
-
-DEFINE_GLOBALS(
+GLOBALS(
 	int fd;
 	char *name;
 )
 
-#define TT this.cmp
-
 // This handles opening the file and 
 
 void do_cmp(int fd, char *name)
--- a/toys/posix/comm.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/comm.c	Mon Oct 08 00:02:30 2012 -0500
@@ -24,12 +24,9 @@
 	  -3 suppress the output column of lines duplicated in FILE1 and FILE2
 */
 
+#define FOR_comm
 #include "toys.h"
 
-#define FLAG_1 1
-#define FLAG_2 2
-#define FLAG_3 4
-
 static void writeline(const char *line, int col)
 {
 	if (col == 0 && toys.optflags & FLAG_1) return;
--- a/toys/posix/cp.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/cp.c	Mon Oct 08 00:02:30 2012 -0500
@@ -6,53 +6,53 @@
  *
  * See http://opengroup.org/onlinepubs/9699919799/utilities/cp.html
  *
- * "R+ra+d+p+r"
-USE_CP(NEWTOY(cp, "<2vslrRdpaHLPif", TOYFLAG_BIN))
+ * TODO: "R+ra+d+p+r" sHLPR
+
+USE_CP(NEWTOY(cp, "<2"USE_CP_MORE("rdavsl")"RHLPfip", TOYFLAG_BIN))
 
 config CP
 	bool "cp (broken by dirtree changes)"
 	default n
 	help
-	  usage: cp -fiprdal SOURCE... DEST
+		usage: cp [-fipRHLP] SOURCE... DEST
 
-	  Copy files from SOURCE to DEST.  If more than one SOURCE, DEST must
-	  be a directory.
+		Copy files from SOURCE to DEST.  If more than one SOURCE, DEST must
+		be a directory.
 
 		-f	force copy by deleting destination file
 		-i	interactive, prompt before overwriting existing DEST
 		-p	preserve timestamps, ownership, and permissions
-		-r	recurse into subdirectories (DEST must be a directory)
+		-R	recurse into subdirectories (DEST must be a directory)
+		-H	Follow symlinks listed on command line
+		-L	Follow all symlinks
+		-P	Do not follow symlinks [default]
+
+config CP_MORE
+	bool "cp -rdavsl options"
+	default y
+	depends on CP
+	help
+		usage: cp [-rdavsl]
+
+		-r	synonym for -R
 		-d	don't dereference symlinks
 		-a	same as -dpr
-		-l	hard link instead of copying
+		-l	hard link instead of copy
+		-s	symlink instead of copy
 		-v	verbose
 */
 
+#define FOR_cp
 #include "toys.h"
 
-#define FLAG_f 1
-#define FLAG_i 2
-#define FLAG_P 4	// todo
-#define FLAG_L 8	// todo
-#define FLAG_H 16	// todo
-#define FLAG_a 32
-#define FLAG_p 64
-#define FLAG_d 128	// todo
-#define FLAG_R 256
-#define FLAG_r 512
-#define FLAG_l 1024	// todo
-#define FLAG_s 2048	// todo
-#define FLAG_v 4098
+// TODO: PLHlsd
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *destname;
 	int destisdir;
-	int destisnew;
 	int keep_symlinks;
 )
 
-#define TT this.cp
-
 // Copy an individual file or directory to target.
 
 void cp_file(char *src, char *dst, struct stat *srcst)
@@ -156,42 +156,36 @@
 
 void cp_main(void)
 {
-	struct stat st;
+	char *dpath = NULL;
+	struct stat st, std;
 	int i;
 
-	// Grab target argument.  (Guaranteed to be there due to "<2" above.)
+	// Identify destination
 
-	TT.destname = toys.optargs[--toys.optc];
+	if (!stat(TT.destname, &std) && S_ISDIR(std.st_mode)) TT.destisdir++;
+	else if (toys.optc>1) error_exit("'%s' not directory", TT.destname);
 
-	// If destination doesn't exist, are we ok with that?
+   // TODO: This is too early: we haven't created it yet if we need to
+	if (toys.optflags & (FLAG_R|FLAG_r|FLAG_a))
+		dpath = realpath(TT.destname = toys.optargs[--toys.optc], NULL);
 
-	if (stat(TT.destname, &st)) {
-		if (toys.optc>1) goto error_notdir;
-		TT.destisnew++;
-
-	// If destination exists...
-
-	} else {
-		if (S_ISDIR(st.st_mode)) TT.destisdir++;
-		else if (toys.optc > 1) goto error_notdir;
-	}
-
-	// Handle sources
+	// Loop through sources
 
 	for (i=0; i<toys.optc; i++) {
-		char *src = toys.optargs[i];
-		char *dst;
+		char *dst, *src = toys.optargs[i];
 
 		// Skip src==dest (TODO check inodes to catch "cp blah ./blah").
 
-		if (!strcmp(src, TT.destname)) continue;
+		if (!strncmp(src, TT.destname)) continue;
 
 		// Skip nonexistent sources.
 
 		TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a);
-		if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st))
+		if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st)
+			|| (st.st_dev = dst.st_dev && st.st_ino == dst.dst_ino))
 		{
-			perror_msg("'%s'", src);
+objection:
+			perror_msg("bad '%s'", src);
 			toys.exitval = 1;
 			continue;
 		}
@@ -199,26 +193,35 @@
 		// Copy directory or file.
 
 		if (TT.destisdir) {
+			char *s;
+
+			// Catch "cp -R .. ." and friends that would go on forever
+			if (dpath && (s = realpath(src, NULL)) {
+				int i = strlen(s);
+				i = (!strncmp(s, dst, i) && (!s[i] || s[i]=='/'));
+				free(s);
+
+				if (i) goto objection;
+			}
+
+			// Create destination filename within directory
 			dst = strrchr(src, '/');
 			if (dst) dst++;
 			else dst=src;
 			dst = xmsprintf("%s/%s", TT.destname, dst);
 		} else dst = TT.destname;
+
 		if (S_ISDIR(st.st_mode)) {
 			if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) {
 				cp_file(src, dst, &st);
 
 				TT.keep_symlinks++;
-				strncpy(toybuf, src, sizeof(toybuf)-1);
-				toybuf[sizeof(toybuf)-1]=0;
-				dirtree_read(toybuf, cp_node);
+				dirtree_read(src, cp_node);
 			} else error_msg("Skipped dir '%s'", src);
 		} else cp_file(src, dst, &st);
 		if (TT.destisdir) free(dst);
 	}
 
+	if (CFG_TOYBOX_FREE) free(dpath);
 	return;
-
-error_notdir:
-	error_exit("'%s' isn't a directory", TT.destname);
 }
--- a/toys/posix/date.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/date.c	Mon Oct 08 00:02:30 2012 -0500
@@ -17,17 +17,13 @@
 	  Set/get the current date/time
 */
 
+#define FOR_date
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
     char *file;
 )
 
-#define TT this.date
-
-#define FLAG_u 1
-#define FLAG_r 2
-
 void date_main(void)
 {
     const char *format_string = "%a %b %e %H:%M:%S %Z %Y";
--- a/toys/posix/df.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/df.c	Mon Oct 08 00:02:30 2012 -0500
@@ -37,16 +37,15 @@
 	  -k	Sets units back to 1024 bytes (the default without -P)
 */
 
+#define FOR_df
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	struct arg_list *fstype;
 
 	long units;
 )
 
-#define TT this.df
-
 static void show_mt(struct mtab_list *mt)
 {
 	int len;
@@ -67,7 +66,7 @@
 	}
 
 	// If we don't have -a, skip synthetic filesystems
-	if (!(toys.optflags & 1) && !mt->statvfs.f_blocks) return;
+	if (!(toys.optflags & FLAG_a) && !mt->statvfs.f_blocks) return;
 
 	// Figure out how much total/used/free space this filesystem has,
 	// forcing 64-bit math because filesystems are big now.
@@ -83,7 +82,7 @@
 	// Figure out appropriate spacing
 	len = 25 - strlen(mt->device);
 	if (len < 1) len = 1;
-	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
+	if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) {
 		printf("%s %ld %ld %ld %ld%% %s\n", mt->device, size, used, avail,
 				percent, mt->dir);
 	} else {
@@ -98,9 +97,9 @@
 
 	// Handle -P and -k
 	TT.units = 1024;
-	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
+	if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) {
 		// Units are 512 bytes if you select "pedantic" without "kilobytes".
-		if ((toys.optflags&3) == 1) TT.units = 512;
+		if ((toys.optflags&(FLAG_P|FLAG_k)) == FLAG_P) TT.units = 512;
 		printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n",
 			TT.units);
 	} else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on");
--- a/toys/posix/du.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/du.c	Mon Oct 08 00:02:30 2012 -0500
@@ -28,9 +28,10 @@
 	  -m    Sizes in megabytes
 */
 
+#define FOR_du
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
     long maxdepth;
     long depth;
 	long *dirsum;
@@ -39,20 +40,6 @@
     struct arg_list *inodes;
 )
 
-#define TT this.du
-
-#define FLAG_x	1
-#define FLAG_s	2
-#define FLAG_L	4
-#define FLAG_k	8
-#define FLAG_H	16
-#define FLAG_a	32
-#define FLAG_c	64
-#define FLAG_l	128
-#define FLAG_m	256
-#define FLAG_h	512
-#define FLAG_d	1024
-
 typedef struct node_size {
     struct dirtree *node;
     long size;
--- a/toys/posix/echo.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/echo.c	Mon Oct 08 00:02:30 2012 -0500
@@ -32,12 +32,9 @@
 	   \xHH	 hexadecimal values (1 to 2 digits)
 */
 
-#define THIS echo
+#define FOR_echo
 #include "toys.h"
 
-#define FLAG_e (1<<1)
-#define FLAG_n (1<<0)
-
 void echo_main(void)
 {
 	int i = 0, out;
--- a/toys/posix/env.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/env.c	Mon Oct 08 00:02:30 2012 -0500
@@ -29,7 +29,7 @@
     char **command = NULL;
     char *del = "=";
     
-    if (toys.optflags & 1) clearenv();
+    if (toys.optflags) clearenv();
     
     for (ev = toys.optargs; *ev != NULL; ev++) {
         char *env, *val = NULL;
--- a/toys/posix/head.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/head.c	Mon Oct 08 00:02:30 2012 -0500
@@ -20,15 +20,14 @@
 	  -n	Number of lines to copy.
 */
 
+#define FOR_head
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long lines;
 	int file_no;
 )
 
-#define TT this.head
-
 static void do_head(int fd, char *name)
 {
 	int i, len, lines=TT.lines, size=sizeof(toybuf);
--- a/toys/posix/id.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/id.c	Mon Oct 08 00:02:30 2012 -0500
@@ -25,14 +25,9 @@
 	  -u    Show only the effective user ID
 */
 
+#define FOR_id
 #include "toys.h"
 
-#define FLAG_n (1<<4)
-#define FLAG_G (1<<3)
-#define FLAG_g (1<<2)
-#define FLAG_r (1<<1)
-#define FLAG_u 1
-
 static void s_or_u(char *s, unsigned u, int done)
 {
 	if (toys.optflags & FLAG_n) printf("%s", s);
--- a/toys/posix/kill.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/kill.c	Mon Oct 08 00:02:30 2012 -0500
@@ -18,14 +18,13 @@
 
 */
 
+#define FOR_kill
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *signame;
 )
 
-#define TT this.kill
-
 void kill_main(void)
 {
 	int signum;
@@ -33,7 +32,7 @@
 	pid_t pid;
 
 	// list signal(s)
-	if (toys.optflags & 1) {
+	if (toys.optflags & FLAG_l) {
 		if (*args) {
 			int signum = sig_to_num(*args);
 			char *s = NULL;
--- a/toys/posix/ln.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/ln.c	Mon Oct 08 00:02:30 2012 -0500
@@ -22,12 +22,9 @@
           -n	Symlink at destination treated as file
 */
 
+#define FOR_ln
 #include "toys.h"
 
-#define FLAG_s	1
-#define FLAG_f	2
-#define FLAG_n	4
-
 void ln_main(void)
 {
     char *dest = toys.optargs[--toys.optc], *new;
--- a/toys/posix/ls.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/ls.c	Mon Oct 08 00:02:30 2012 -0500
@@ -50,40 +50,14 @@
 	  -S	size
 */
 
+#define FOR_ls
 #include "toys.h"
 
-#define FLAG_1 (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_u (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_s (1<<4)
-#define FLAG_r (1<<5)
-#define FLAG_q (1<<6)
-#define FLAG_p (1<<7)
-#define FLAG_n (1<<8)
-#define FLAG_m (1<<9)
-#define FLAG_l (1<<10)
-#define FLAG_k (1<<11)
-#define FLAG_i (1<<12)
-#define FLAG_f (1<<13)
-#define FLAG_d (1<<14)
-#define FLAG_c (1<<15)
-#define FLAG_a (1<<16)
-#define FLAG_S (1<<17)
-#define FLAG_R (1<<18)
-#define FLAG_L (1<<19)
-#define FLAG_H (1<<20)
-#define FLAG_F (1<<21)
-#define FLAG_C (1<<22)
-#define FLAG_A (1<<23)
-#define FLAG_o (1<<24)
-#define FLAG_g (1<<25)
-
 // test sst output (suid/sticky in ls flaglist)
 
 // ls -lR starts .: then ./subdir:
 
-DEFINE_GLOBALS(
+GLOBALS(
     struct dirtree *files;
 
     unsigned screen_width;
@@ -93,8 +67,6 @@
     char uid_buf[12];
 )
 
-#define TT this.ls
-
 void dlist_to_dirtree(struct dirtree *parent)
 {
     // Turn double_list into dirtree
--- a/toys/posix/mkdir.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/mkdir.c	Mon Oct 08 00:02:30 2012 -0500
@@ -20,14 +20,13 @@
 	  -p	make parent directories as needed.
 */
 
+#define FOR_mkdir
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long mode;
 )
 
-#define TT this.mkdir
-
 static int do_mkdir(char *dir)
 {
 	struct stat buf;
--- a/toys/posix/mkfifo.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/mkfifo.c	Mon Oct 08 00:02:30 2012 -0500
@@ -19,16 +19,14 @@
 	  Create FIFOs (named pipes).
 */
 
+#define FOR_mkfifo
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *m_string;
 	mode_t mode;
 )
 
-#define TT this.mkfifo
-#define FLAG_m (1)
-
 void mkfifo_main(void)
 {
 	char **s;
--- a/toys/posix/nice.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/nice.c	Mon Oct 08 00:02:30 2012 -0500
@@ -22,14 +22,13 @@
 	  priority.  Only root can set a negative niceness level.
 */
 
+#define FOR_nice
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long priority;
 )
 
-#define TT this.nice
-
 void nice_main(void)
 {
 	if (!toys.optflags) TT.priority = 10;
--- a/toys/posix/od.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/od.c	Mon Oct 08 00:02:30 2012 -0500
@@ -19,20 +19,10 @@
 	  -t	output type(s) a (ascii) c (char) d (decimal) foux
 */
 
+#define FOR_od
 #include "toys.h"
 
-#define FLAG_t	(1 << 0)
-#define FLAG_A	(1 << 1)
-#define FLAG_b	(1 << 2)
-#define FLAG_c	(1 << 3)
-#define FLAG_d	(1 << 4)
-#define FLAG_o	(1 << 5)
-#define FLAG_s	(1 << 6)
-#define FLAG_x	(1 << 7)
-#define FLAG_N	(1 << 8)
-#define FLAG_v  (1 << 9)
-
-DEFINE_GLOBALS(
+GLOBALS(
 	struct arg_list *output_base;
 	char *address_base;
 	long max_count;
@@ -44,8 +34,6 @@
 	off_t pos;
 )
 
-#define TT this.od
-
 static char *ascii = "nulsohstxetxeotenqackbel bs ht nl vt ff cr so si"
 	"dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us sp";
 
--- a/toys/posix/patch.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/patch.c	Mon Oct 08 00:02:30 2012 -0500
@@ -45,9 +45,10 @@
 	  created/deleted as appropriate.
 */
 
+#define FOR_patch
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *infile;
 	long prefix;
 
@@ -58,14 +59,6 @@
 	char *tempname;
 )
 
-#define TT this.patch
-
-#define FLAG_R (1<<0)
-#define FLAG_i (1<<1)
-#define FLAG_l (1<<2)
-#define FLAG_p (1<<3)
-#define FLAG_u (1<<4)
-
 // Dispose of a line of input, either by writing it out or discarding it.
 
 // state < 2: just free
--- a/toys/posix/sed.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/sed.c	Mon Oct 08 00:02:30 2012 -0500
@@ -18,15 +18,14 @@
 	  of input.
 */
 
+#define FOR_sed
 #include "toys.h"
 #include "lib/xregcomp.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	struct arg_list *commands;
 )
 
-#define TT this.sed
-
 struct sed_command {
 	// Doubly linked list of commands.
 	struct sed_command *next, *prev;
--- a/toys/posix/sh.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/sh.c	Mon Oct 08 00:02:30 2012 -0500
@@ -176,14 +176,13 @@
 	  -L    Cancel previous -P and restore default behavior.
 */
 
+#define FOR_sh
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	char *command;
 )
 
-#define TT this.sh
-
 // A single executable, its arguments, and other information we know about it.
 #define SH_FLAG_EXIT    1
 #define SH_FLAG_SUSPEND 2
--- a/toys/posix/sort.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/sort.c	Mon Oct 08 00:02:30 2012 -0500
@@ -60,9 +60,10 @@
 
 */
 
+#define FOR_sort
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
     char *key_separator;
     struct arg_list *raw_keys;
     char *outfile;
@@ -73,30 +74,11 @@
     char **lines;
 )
 
-#define TT this.sort
-
 // The sort types are n, g, and M.
 // u, c, s, and z apply to top level only, not to keys.
 // b at top level implies bb.
 // The remaining options can be applied to search keys.
 
-#define FLAG_n  (1<<0)  // Sort type: numeric
-#define FLAG_u  (1<<1)  // Unique
-#define FLAG_r  (1<<2)  // Reverse output order
-
-#define FLAG_i  (1<<3)  // Ignore !isprint()
-#define FLAG_f  (1<<4)  // Force uppercase
-#define FLAG_d  (1<<5)  // Ignore !(isalnum()|isspace())
-#define FLAG_z  (1<<6)  // Input is null terminated, not \n
-#define FLAG_s  (1<<7)  // Stable sort, no ascii fallback at end
-#define FLAG_c  (1<<8)  // Check only.  No output, exit(!ordered)
-#define FLAG_M  (1<<9)  // Sort type: date
-#define FLAG_b  (1<<10) // Ignore leading blanks
-#define FLAG_x  (1<<11) // Hex sort
-#define FLAG_g  (1<<18) // Sort type: strtod()
-
-// Left off dealing with FLAG_b/FLAG_bb logic...
-
 #define FLAG_bb (1<<31)  // Ignore trailing blanks
 
 struct sort_key
--- a/toys/posix/tail.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/tail.c	Mon Oct 08 00:02:30 2012 -0500
@@ -29,21 +29,16 @@
 		This version uses lseek, which is faster on large files.
 */
 
+#define FOR_tail
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long lines;
 	long bytes;
 
 	int file_no;
 )
 
-#define TT this.tail
-
-#define FLAG_n 1
-#define FLAG_c 2
-#define FLAG_f 4
-
 struct line_list {
 	struct line_list *next, *prev;
 	char *data;
--- a/toys/posix/tee.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/tee.c	Mon Oct 08 00:02:30 2012 -0500
@@ -21,14 +21,13 @@
       -i	ignore SIGINT.
 */
 
+#define FOR_tee
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
     void *outputs;
 )
 
-#define TT this.tee
-
 struct fd_list {
     struct fd_list *next;
     int fd;
@@ -48,12 +47,12 @@
 
 void tee_main(void)
 {
-    if (toys.optflags&2) signal(SIGINT, SIG_IGN);
+    if (toys.optflags & FLAG_i) signal(SIGINT, SIG_IGN);
 
     // Open output files
     loopfiles_rw(toys.optargs,
-		O_RDWR|O_CREAT|((toys.optflags&1)?O_APPEND:O_TRUNC), 0666, 0,
-		do_tee_open);
+		O_RDWR|O_CREAT|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC),
+		0666, 0, do_tee_open);
 
     for (;;) {
         struct fd_list *fdl;
--- a/toys/posix/uname.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/uname.c	Mon Oct 08 00:02:30 2012 -0500
@@ -24,6 +24,7 @@
 	  -a	All of the above
 */
 
+#define FOR_uname
 #include "toys.h"
 
 // If a 32 bit x86 build environment working in a chroot under an x86-64
@@ -39,15 +40,13 @@
 #define GROSS "i386"
 #endif
 
-#define FLAG_a (1<<5)
-
 void uname_main(void)
 {
 	int i, flags = toys.optflags, needspace=0;
 
 	uname((void *)toybuf);
 
-	if (!flags) flags=1;
+	if (!flags) flags = FLAG_s;
 	for (i=0; i<5; i++) {
 		char *c = toybuf+(65*i);
 
--- a/toys/posix/uniq.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/uniq.c	Mon Oct 08 00:02:30 2012 -0500
@@ -26,23 +26,16 @@
 	  -s	ignore first X chars
 */
 
+#define FOR_uniq
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long maxchars;
 	long nchars;
 	long nfields;
 	long repeats;
 )
 
-#define TT this.uniq
-
-#define FLAG_z 16
-#define FLAG_i 8
-#define FLAG_c 4
-#define FLAG_d 2
-#define FLAG_u 1
-
 static char *skip(char *str)
 {
 	long nchars = TT.nchars, nfields;
--- a/toys/posix/wc.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/wc.c	Mon Oct 08 00:02:30 2012 -0500
@@ -24,14 +24,13 @@
 	  argument (or from stdin if none).
 */
 
+#define FOR_wc
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	unsigned long totals[3];
 )
 
-#define TT this.wc
-
 static void show_lengths(unsigned long *lengths, char *name)
 {
 	int i, nospace = 1;
--- a/toys/posix/xargs.c	Sun Oct 07 23:53:25 2012 -0500
+++ b/toys/posix/xargs.c	Mon Oct 08 00:02:30 2012 -0500
@@ -29,9 +29,10 @@
 	  -E	stop at line matching string
 */
 
+#define FOR_xargs
 #include "toys.h"
 
-DEFINE_GLOBALS(
+GLOBALS(
 	long max_bytes;
 	long max_entries;
 	long L;
@@ -42,8 +43,6 @@
 	char delim;
 )
 
-#define TT this.xargs
-
 // If out==NULL count TT.bytes and TT.entries, stopping at max.
 // Otherwise, fill out out[] 
 
@@ -105,7 +104,7 @@
 	int entries, bytes, done = 0, status;
 	char *data = NULL;
 
-	if (!(toys.optflags&1)) TT.delim = '\n';
+	if (!(toys.optflags & FLAG_0)) TT.delim = '\n';
 
 	// If no optargs, call echo.
 	if (!toys.optc) {
--- a/www/code.html	Sun Oct 07 23:53:25 2012 -0500
+++ b/www/code.html	Mon Oct 08 00:02:30 2012 -0500
@@ -74,7 +74,8 @@
 <li><a href="#lib_dirtree">lib/dirtree.c</a></li>
 </ul>
 <li>The <a href="#toys">toys directory</a> contains the C files implementating
-each command.</li>
+each command. Currently it contains three subdirectories:
+posix, lsb, and other.</li>
 <li>The <a href="#scripts">scripts directory</a> contains the build and
 test infrastructure.</li>
 <li>The <a href="#kconfig">kconfig directory</a> contains the configuration
@@ -85,13 +86,18 @@
 
 <a name="adding" />
 <p><h1>Adding a new command</h1></p>
-<p>To add a new command to toybox, add a C file implementing that command to
+<p>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
 <a href="#generated">"generated" directory</a> for details.)</p>
 
-<p>An easy way to start a new command is copy the file "hello.c" to
+<p>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.)</p>
+
+<p>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 @@
 <p>Here's a checklist of steps to turn hello.c into another command:</p>
 
 <ul>
-<li><p>First "cd toys" and "cp hello.c yourcommand.c".  Note that the name
+<li><p>First "cd toys/other" and "cp hello.c yourcommand.c".  Note that the name
 of this file is significant, it's the name of the new command you're adding
 to toybox.  Open your new file in your favorite editor.</p></li>
 
@@ -114,12 +120,9 @@
 <li><p>Change the copyright notice to your name, email, and the current
 year.</p></li>
 
-<li><p>Give a URL to the relevant standards document, or say "Not in SUSv4" if
-there is no relevant standard.  (Currently both lines are there, delete
-whichever is inappropriate.)  The existing link goes to the directory of SUSv4
-command line utility standards on the Open Group's website, where there's often
-a relevant commandname.html file.  Feel free to link to other documentation or
-standards as appropriate.</p></li>
+<li><p>Give a URL to the relevant standards document, where applicable.
+(Sample links to SUSv4 and LSB are provided, feel free to link to other
+documentation or standards as appropriate.)</p></li>
 
 <li><p>Update the USE_YOURCOMMAND(NEWTOY(yourcommand,"blah",0)) line.
 The NEWTOY macro fills out this command's <a href="#toy_list">toy_list</a>
@@ -153,24 +156,29 @@
 options when producing generated/help.h.</p>
 </li>
 
-<li><p>Update the DEFINE_GLOBALS() macro to contain your command's global
-variables, and also change the name "hello" in the #define TT line afterwards
-to the name of your command.  If your command has no global variables, delete
-this macro (and the #define TT line afterwards).  Note that if you specified
-two-character command line arguments in NEWTOY(), the first few global
-variables will be initialized by the automatic argument parsing logic, and
-the type and order of these variables must correspond to the arguments
-specified in NEWTOY().  See [TODO] for details.</p></li>
+<li><p>Change the "#define FOR_hello" line to "#define FOR_yourcommand" right
+before the "#include <toys.h>". (This selects the appropriate FLAG_ macros and
+does a "#define TT this.yourcommand" so you can access the global variables
+out of the space-saving union of structures. If you aren't using any command
+flag bits and aren't defining a GLOBAL block, you can delete this line.)</p></li>
 
-<li><p>If you didn't delete the DEFINE_GLOBALS macro, change the "#define TT
-this.hello" line to use your command name in place of the "hello".  This is a
-shortcut to access your global variables as if they were members of the global
-struct "TT".  (Access these members with a period ".", not a right arrow
-"->".)</p></li>
+<li><p>Update the GLOBALS() macro to contain your command's global
+variables. If your command has no global variables, delete this macro.</p>
+
+<p>Variables in the GLOBALS() block are are stored in a space saving
+<a href="#toy_union">union of structures</a> format, which may be accessed
+using the TT macro as if TT were a global structure (so TT.membername).
+If you specified two-character command line arguments in
+NEWTOY(), the first few global variables will be initialized by the automatic
+argument parsing logic, and the type and order of these variables must
+correspond to the arguments specified in NEWTOY().
+(See <a href="#lib_args">lib/args.c</a> for details.)</p></li>
 
 <li><p>Rename hello_main() to yourcommand_main().  This is the main() function
-where execution of your command starts.  See [TODO] to figure out what
-happened to your command line arguments and how to access them.</p></li>
+where execution of your command starts. Your command line options are
+already sorted into this.optflags, this.optargs, this.optc, and the GLOBALS()
+as appropriate by the time this function is called. (See
+<a href="#lib_args">get_optflags()</a> for details.</p></li>
 </ul>
 
 <p><a name="top" /><h2>Top level directory.</h2></p>
@@ -178,7 +186,9 @@
 <p>This directory contains global infrastructure.</p>
 
 <h3>toys.h</h3>
-<p>Each command #includes "toys.h" as part of its standard prolog.</p>
+<p>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.</p>
 
 <p>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 @@
 command.</p></li>
 <li><p>char *<b>options</b> - 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().</p></li>
 <li><p>int <b>flags</b> - Behavior flags for this command.  The following flags are currently understood:</p>
 
@@ -269,7 +279,7 @@
 "ps" output, and is not recommended.  This array is null terminated; a NULL
 entry indicates the end of the array.</p>
 <p>Most commands don't use this field, instead the use optargs, optflags,
-and the fields in the DEFINE_GLOBALS struct initialized by get_optflags().</p>
+and the fields in the GLOBALS struct initialized by get_optflags().</p>
 </li>
 <li><p>unsigned <b>optflags</b> - Command line option flags, set by
 <a href="#lib_args">get_optflags()</a>.  Indicates which of the command line options listed in
@@ -282,8 +292,15 @@
 "-a" would set optflags to 8, and "-bd" would set optflags to 6 (4|2).</p>
 
 <p>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).</p>
+b=4, a=8.  Punctuation after a letter initializes global variables at the
+start of the GLOBALS() block (see <a href="#toy_union">union toy_union this</a>
+for details).</p>
+
+<p>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.)</p>
 
 <p>For more information on option parsing, see <a href="#lib_args">get_optflags()</a>.</p>
 
@@ -299,6 +316,7 @@
 false afterwards.)</p></li>
 </ul>
 
+<a name="toy_union" />
 <li><p><b>union toy_union this</b> - Union of structures containing each
 command's global variables.</p>
 
@@ -313,11 +331,12 @@
 
 <p>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.</p>
+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.</p>
 
 <p>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 @@
 <p>If the command's globals are:</p>
 
 <blockquote><pre>
-DECLARE_GLOBALS(
+GLOBALS(
 	char *c;
 	char *b;
 	long a;
 )
-#define TT this.command
 </pre></blockquote>
 <p>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().</p>
+top to bottom in GLOBALS().</p>
 
 <p><b>long toys.optflags</b></p>
 
@@ -940,6 +958,28 @@
 of traversal order, which is neither depth first nor breadth first but
 instead a sort of FIFO order requried by the ls standard.</p>
 
+<a name="#toys">
+<h2>Directory toys/</h2>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<p>(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.)</p>
+
+<p>See <a href="#adding">adding a new command</a> for details on the
+layout of a command file.</p>
+
 <h2>Directory scripts/</h2>
 
 <h3>scripts/cfg2files.sh</h3>