changeset 237:7cb15eae1664

Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS() macros in each C file, and making generated/globals.h from that. Rename "toy" to "this" along the way to avoid toy/toys confusion.
author Rob Landley <rob@landley.net>
date Sun, 20 Jan 2008 17:25:44 -0600
parents 6b292ee780ab
children 630b2e12db16
files Makefile lib/args.c main.c scripts/install.c scripts/make.sh toys.h toys/df.c toys/dmesg.c toys/mke2fs.c toys/mkfifo.c toys/netcat.c toys/oneit.c toys/patch.c toys/sed.c toys/sleep.c toys/touch.c toys/toylist.h toys/toysh.c
diffstat 18 files changed, 201 insertions(+), 183 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sat Jan 19 17:55:45 2008 -0600
+++ b/Makefile	Sun Jan 20 17:25:44 2008 -0600
@@ -34,7 +34,7 @@
 
 clean::
 	rm -f toybox toybox_unstripped generated/config.h generated/Config.in \
-		generated/newtoys.h instlist
+		generated/newtoys.h generated/globals.h instlist
 
 distclean: clean
 	rm -f toybox_old .config* generated/help.h
--- a/lib/args.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/lib/args.c	Sun Jan 20 17:25:44 2008 -0600
@@ -130,7 +130,7 @@
 		char *str;
 		int len;
 	} *longopts = NULL;
-	long *nextarg = (long *)&toy;
+	long *nextarg = (long *)&this;
 	char *options = toys.which->options;
 
 	if (CFG_HELP) toys.exithelp++;
--- a/main.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/main.c	Sun Jan 20 17:25:44 2008 -0600
@@ -22,7 +22,7 @@
 // global context for this applet.
 
 struct toy_context toys;
-union toy_union toy;
+union global_union this;
 char toybuf[4096];
 
 struct toy_list *toy_find(char *name)
--- a/scripts/install.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/scripts/install.c	Sun Jan 20 17:25:44 2008 -0600
@@ -14,7 +14,7 @@
 // Populate toy_list[].
 
 struct toy_list toy_list[] = {
-#include "toys/toylist.h"
+#include "generated/newtoys.h"
 };
 
 #define TOY_LIST_LEN (sizeof(toy_list)/sizeof(struct toy_list))
--- a/scripts/make.sh	Sat Jan 19 17:55:45 2008 -0600
+++ b/scripts/make.sh	Sun Jan 20 17:25:44 2008 -0600
@@ -4,9 +4,11 @@
 
 source ./configure
 
-echo "Extract configuration information from toys/*.c files."
+echo "Extract configuration information from toys/*.c files..."
 scripts/genconfig.sh
 
+echo "Generate headers from toys/*.h..."
+
 # 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
@@ -22,6 +24,30 @@
 echo "NEWTOY(toybox, NULL, 0)" > generated/newtoys.h
 newtoys | sort >> generated/newtoys.h
 
+# Extract global structure definitions from toys/*.c
+
+function getglobals()
+{
+  for i in toys/*.c
+  do
+    NAME="$(echo $i | sed 's@toys/\(.*\)\.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
+  done
+}
+
+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
+
 # Only recreate generated/help.h if python is installed
 if [ ! -z "$(which python)" ] && [ ! -z "$(grep 'CONFIG_HELP=y' .config)" ]
 then
--- a/toys.h	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys.h	Sun Jan 20 17:25:44 2008 -0600
@@ -39,13 +39,13 @@
 
 #include "lib/lib.h"
 #include "toys/e2fs.h"
-#include "toys/toylist.h"
 
 // Get list of function prototypes for all enabled command_main() functions.
 
 #define NEWTOY(name, opts, flags) void name##_main(void);
 #define OLDTOY(name, oldname, opts, flags)
 #include "generated/newtoys.h"
+#include "generated/globals.h"
 
 // These live in main.c
 
@@ -53,6 +53,22 @@
 void toy_init(struct toy_list *which, char *argv[]);
 void toy_exec(char *argv[]);
 
+// List of available applets
+
+#define TOYFLAG_USR      (1<<0)
+#define TOYFLAG_BIN      (1<<1)
+#define TOYFLAG_SBIN     (1<<2)
+#define TOYMASK_LOCATION ((1<<4)-1)
+
+#define TOYFLAG_NOFORK   (1<<4)
+
+extern struct toy_list {
+        char *name;
+        void (*toy_main)(void);
+        char *options;
+        int flags;
+} toy_list[];
+
 // Global context for any applet.
 
 extern struct toy_context {
@@ -67,3 +83,5 @@
 // One big temporary buffer, for use by applets (not library functions).
 
 extern char toybuf[4096];
+
+#define DEFINE_GLOBALS(...)
--- a/toys/df.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/df.c	Sun Jan 20 17:25:44 2008 -0600
@@ -39,6 +39,14 @@
 
 #include "toys.h"
 
+DEFINE_GLOBALS(
+	struct arg_list *fstype;
+
+	long units;
+)
+
+#define TT this.df
+
 static void show_mt(struct mtab_list *mt)
 {
 	int len;
@@ -49,10 +57,10 @@
 	if (!mt) return;
 
 	// If we have -t, skip other filesystem types
-	if (toy.df.fstype) {
+	if (TT.fstype) {
 		struct arg_list *al;
 
-		for (al = toy.df.fstype; al; al = al->next) {
+		for (al = TT.fstype; al; al = al->next) {
 			if (!strcmp(mt->type, al->arg)) break;
 		}
 		if (!al) return;
@@ -64,12 +72,12 @@
 	// Figure out how much total/used/free space this filesystem has,
 	// forcing 64-bit math because filesystems are big now.
 	block = mt->statvfs.f_bsize ? : 1;
-	size = (long)((block * mt->statvfs.f_blocks) / toy.df.units);
+	size = (long)((block * mt->statvfs.f_blocks) / TT.units);
 	used = (long)((block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree))
-			/ toy.df.units);
+			/ TT.units);
 	avail = (long)((block
 				* (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree))
-			/ toy.df.units);
+			/ TT.units);
 	percent = size ? 100-(long)((100*(uint64_t)avail)/size) : 0;
 
 	// Figure out appropriate spacing
@@ -89,12 +97,12 @@
 	struct mtab_list *mt, *mt2, *mtlist;
 
 	// Handle -P and -k
-	toy.df.units = 1024;
+	TT.units = 1024;
 	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
 		// Units are 512 bytes if you select "pedantic" without "kilobytes".
-		if ((toys.optflags&3) == 1) toy.df.units = 512;
+		if ((toys.optflags&3) == 1) TT.units = 512;
 		printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n",
-			toy.df.units);
+			TT.units);
 	} else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on");
 
 	mtlist = getmountlist(1);
--- a/toys/dmesg.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/dmesg.c	Sun Jan 20 17:25:44 2008 -0600
@@ -24,7 +24,12 @@
 #include "toys.h"
 #include <sys/klog.h>
 
-#define TT toy.dmesg
+DEFINE_GLOBALS(
+	long level;
+	long size;
+)
+
+#define TT this.dmesg
 
 void dmesg_main(void)
 {
--- a/toys/mke2fs.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/mke2fs.c	Sun Jan 20 17:25:44 2008 -0600
@@ -77,8 +77,35 @@
 
 #include "toys.h"
 
+DEFINE_GLOBALS(
+	// Command line arguments.
+	long blocksize;
+	long bytes_per_inode;
+	long inodes;           // Total inodes in filesystem.
+	long reserved_percent; // Integer precent of space to reserve for root.
+	char *gendir;          // Where to read dirtree from.
+
+	// Internal data.
+	struct dirtree *dt;    // Tree of files to copy into the new filesystem.
+	unsigned treeblocks;   // Blocks used by dt
+	unsigned treeinodes;   // Inodes used by dt
+
+	unsigned blocks;       // Total blocks in the filesystem.
+	unsigned freeblocks;   // Free blocks in the filesystem.
+	unsigned inodespg;     // Inodes per group
+	unsigned groups;       // Total number of block groups.
+	unsigned blockbits;    // Bits per block.  (Also blocks per group.)
+
+	// For gene2fs
+	unsigned nextblock;    // Next data block to allocate
+	unsigned nextgroup;    // Next group we'll be allocating from
+	int fsfd;              // File descriptor of filesystem (to output to).
+
+	struct ext2_superblock sb;
+)
+
 // Shortcut to our global data structure, since we use it so much.
-#define TT toy.mke2fs
+#define TT this.mke2fs
 
 #define INODES_RESERVED 10
 
@@ -140,20 +167,20 @@
 // Returns blocks used by this directory, assigns bytes used to *size.
 // Writes total block count to TT.treeblocks and inode count to TT.treeinodes.
 
-static long check_treesize(struct dirtree *this, off_t *size)
+static long check_treesize(struct dirtree *that, off_t *size)
 {
 	long blocks;
 
-	while (this) {
-		*size += sizeof(struct ext2_dentry) + strlen(this->name);
+	while (that) {
+		*size += sizeof(struct ext2_dentry) + strlen(that->name);
 
-		if (this->child)
-			this->st.st_blocks = check_treesize(this->child, &this->st.st_size);
-		else if (S_ISREG(this->st.st_mode)) {
-			 this->st.st_blocks = file_blocks_used(this->st.st_size, 0);
-			 TT.treeblocks += this->st.st_blocks;
+		if (that->child)
+			that->st.st_blocks = check_treesize(that->child, &that->st.st_size);
+		else if (S_ISREG(that->st.st_mode)) {
+			 that->st.st_blocks = file_blocks_used(that->st.st_size, 0);
+			 TT.treeblocks += that->st.st_blocks;
 		}
-		this = this->next;
+		that = that->next;
 	}
 	TT.treeblocks += blocks = file_blocks_used(*size, 0);
 	TT.treeinodes++;
@@ -170,30 +197,31 @@
 
 static void check_treelinks(struct dirtree *tree)
 {
-	struct dirtree *this=tree, *that;
+	struct dirtree *current=tree, *that;
 	long inode = INODES_RESERVED;
 
-	while (this) {
+	while (current) {
 		++inode;
 		// Since we can't hardlink to directories, we know their link count.
-		if (S_ISDIR(this->st.st_mode)) this->st.st_nlink = 2;
+		if (S_ISDIR(current->st.st_mode)) current->st.st_nlink = 2;
 		else {
-			dev_t new = this->st.st_dev;
+			dev_t new = current->st.st_dev;
 
 			if (!new) continue;
 
-			this->st.st_nlink = 0;
+			// Look for other copies of current node
+			current->st.st_nlink = 0;
 			for (that = tree; that; that = treenext(that)) {
-				if (this->st.st_ino == that->st.st_ino &&
-					this->st.st_dev == that->st.st_dev)
+				if (current->st.st_ino == that->st.st_ino &&
+					current->st.st_dev == that->st.st_dev)
 				{
-					this->st.st_nlink++;
-					this->st.st_ino = inode;
+					current->st.st_nlink++;
+					current->st.st_ino = inode;
 				}
 			}
 		}
-		this->st.st_ino = inode;
-		this = treenext(this);
+		current->st.st_ino = inode;
+		current = treenext(current);
 	}
 }
 
@@ -363,15 +391,15 @@
 }
 
 // Fill out an inode structure from struct stat info in dirtree.
-static void fill_inode(struct ext2_inode *in, struct dirtree *this)
+static void fill_inode(struct ext2_inode *in, struct dirtree *that)
 {
 	uint32_t fbu[15];
 	int temp;
 
-	file_blocks_used(this->st.st_size, fbu);
+	file_blocks_used(that->st.st_size, fbu);
 
-	// If this inode needs data blocks allocated to it.
-	if (this->st.st_size) {
+	// If that inode needs data blocks allocated to it.
+	if (that->st.st_size) {
 		int i, group = TT.nextblock/TT.blockbits;
 
 		// TODO: teach this about indirect blocks.
@@ -382,26 +410,26 @@
 		}
 	}
 	// TODO :  S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m)
-	in->mode = SWAP_LE32(this->st.st_mode);
+	in->mode = SWAP_LE32(that->st.st_mode);
 
-	in->uid = SWAP_LE16(this->st.st_uid & 0xFFFF);
-	in->uid_high = SWAP_LE16(this->st.st_uid >> 16);
-	in->gid = SWAP_LE16(this->st.st_gid & 0xFFFF);
-	in->gid_high = SWAP_LE16(this->st.st_gid >> 16);
-	in->size = SWAP_LE32(this->st.st_size & 0xFFFFFFFF);
+	in->uid = SWAP_LE16(that->st.st_uid & 0xFFFF);
+	in->uid_high = SWAP_LE16(that->st.st_uid >> 16);
+	in->gid = SWAP_LE16(that->st.st_gid & 0xFFFF);
+	in->gid_high = SWAP_LE16(that->st.st_gid >> 16);
+	in->size = SWAP_LE32(that->st.st_size & 0xFFFFFFFF);
 
 	// Contortions to make the compiler not generate a warning for x>>32
 	// when x is 32 bits.  The optimizer should clean this up.
-	if (sizeof(this->st.st_size) > 4) temp = 32;
+	if (sizeof(that->st.st_size) > 4) temp = 32;
 	else temp = 0;
-	if (temp) in->dir_acl = SWAP_LE32(this->st.st_size >> temp);
+	if (temp) in->dir_acl = SWAP_LE32(that->st.st_size >> temp);
 	
-	in->atime = SWAP_LE32(this->st.st_atime);
-	in->ctime = SWAP_LE32(this->st.st_ctime);
-	in->mtime = SWAP_LE32(this->st.st_mtime);
+	in->atime = SWAP_LE32(that->st.st_atime);
+	in->ctime = SWAP_LE32(that->st.st_ctime);
+	in->mtime = SWAP_LE32(that->st.st_mtime);
 
-	in->links_count = SWAP_LE16(this->st.st_nlink);
-	in->blocks = SWAP_LE32(this->st.st_blocks);
+	in->links_count = SWAP_LE16(that->st.st_nlink);
+	in->blocks = SWAP_LE32(that->st.st_blocks);
 	// in->faddr
 }
 
--- a/toys/mkfifo.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/mkfifo.c	Sun Jan 20 17:25:44 2008 -0600
@@ -21,6 +21,12 @@
 
 #include "toys.h"
 
+DEFINE_GLOBALS(
+	char *mode;
+)
+
+#define TT this.mkfifo
+
 void mkfifo_main(void)
 {
 	char *arg;
@@ -29,8 +35,8 @@
 
 	if (toys.optflags) {
 		char *end;
-		mode = (mode_t)strtol(toy.mkfifo.mode, &end, 8);
-		if (end<=toy.mkfifo.mode || *end || mode<0 || mode>0777)
+		mode = (mode_t)strtol(TT.mode, &end, 8);
+		if (end<=TT.mode || *end || mode<0 || mode>0777)
 			error_exit("Invalid mode");
 	} else mode = 0644;
 
--- a/toys/netcat.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/netcat.c	Sun Jan 20 17:25:44 2008 -0600
@@ -33,7 +33,17 @@
 #include "toys.h"
 #include "toynet.h"
 
-#define TT toy.netcat
+DEFINE_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.
+	long port;             // -p Bind to a specific source port.
+	long listen;           // -l Listen for connection instead of dialing out.
+	long wait;             // -w Wait # seconds for a connection.
+	long delay;            // -i delay between lines sent
+)
+
+#define TT this.netcat
 
 static void timeout(int signum)
 {
--- a/toys/oneit.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/oneit.c	Sun Jan 20 17:25:44 2008 -0600
@@ -29,6 +29,12 @@
 #include "toys.h"
 #include <sys/reboot.h>
 
+DEFINE_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).
@@ -39,7 +45,6 @@
 // PID 1 then reaps zombies until the child process it spawned exits, at which
 // point it calls sync() and reboot().  I could stick a kill -1 in there.
 
-#define TT toy.oneit
 
 void oneit_main(void)
 {
--- a/toys/patch.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/patch.c	Sun Jan 20 17:25:44 2008 -0600
@@ -45,7 +45,17 @@
 
 #include "toys.h"
 
-#define TT toy.patch
+DEFINE_GLOBALS(
+	char *infile;
+	long prefix;
+
+	struct double_list *plines, *flines;
+	long oldline, oldlen, newline, newlen, linenum;
+	int context, state, filein, fileout, filepatch;
+	char *tempname, *oldname;
+)
+
+#define TT this.patch
 
 #define FLAG_REVERSE 1
 #define FLAG_PATHLEN 4
--- a/toys/sed.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/sed.c	Sun Jan 20 17:25:44 2008 -0600
@@ -21,6 +21,12 @@
 #include "toys.h"
 #include "lib/xregcomp.h"
 
+DEFINE_GLOBALS(
+	struct arg_list *commands;
+)
+
+#define TT this.sed
+
 struct sed_command {
 	// Doubly linked list of commands.
 	struct sed_command *next, *prev;
@@ -46,8 +52,6 @@
 	char command;
 };
 
-#define TT toy.sed
-
 void sed_main(void)
 {
 	struct arg_list *test;
--- a/toys/sleep.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/sleep.c	Sun Jan 20 17:25:44 2008 -0600
@@ -19,6 +19,10 @@
 
 #include "toys.h"
 
+DEFINE_GLOBALS(
+	long seconds;
+)
+
 void sleep_main(void)
 {
 	toys.exitval = sleep(atol(*toys.optargs));
--- a/toys/touch.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/touch.c	Sun Jan 20 17:25:44 2008 -0600
@@ -26,6 +26,14 @@
 
 #include "toys.h"
 
+DEFINE_GLOBALS(
+	char *ref_file;
+	char *time;
+	long length;
+)
+
+#define TT this.touch
+
 #define OPT_MTIME       0x01
 #define OPT_NOCREATE    0x02
 #define OPT_ATIME       0x04
@@ -48,7 +56,7 @@
 
 		if (toys.optflags & OPT_TIME)
 			error_exit("Redundant time source");
-		xstat(toy.touch.ref_file, &sb);
+		xstat(TT.ref_file, &sb);
 		curr_m = sb.st_mtime;
 		curr_a = sb.st_atime;
 
@@ -60,10 +68,10 @@
 
 		curr = time(NULL);
 		if (localtime_r(&curr, &t)
-			|| !(c = strptime(toy.touch.time, "%m%d%H%M", &t))
+			|| !(c = strptime(TT.time, "%m%d%H%M", &t))
 			|| *c || -1==(curr_a = curr_m = mktime(&t)))
 		{
-			error_exit("Unknown time %s", toy.touch.time);
+			error_exit("Unknown time %s", TT.time);
 		}
 
 	// use current time
@@ -93,7 +101,7 @@
 		}
 
 		if (toys.optflags & OPT_LENGTH)
-			if (truncate(arg, toy.touch.length))
+			if (truncate(arg, TT.length))
 				goto error;
 		if (utime(arg, &buf))
 error:
--- a/toys/toylist.h	Sat Jan 19 17:55:45 2008 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/* vi: set ts=4 :*/
-/* Toybox infrastructure.
- *
- * Copyright 2006 Rob Landley <rob@landley.net>
- */
-
-
-struct df_data {
-	struct arg_list *fstype;
-
-	long units;
-};
-
-struct dmesg_data {
-	long level;
-	long size;
-};
-
-struct mke2fs_data {
-	// Command line arguments.
-	long blocksize;
-	long bytes_per_inode;
-	long inodes;           // Total inodes in filesystem.
-	long reserved_percent; // Integer precent of space to reserve for root.
-	char *gendir;          // Where to read dirtree from.
-
-	// Internal data.
-	struct dirtree *dt;    // Tree of files to copy into the new filesystem.
-	unsigned treeblocks;   // Blocks used by dt
-	unsigned treeinodes;   // Inodes used by dt
-
-	unsigned blocks;       // Total blocks in the filesystem.
-	unsigned freeblocks;   // Free blocks in the filesystem.
-	unsigned inodespg;     // Inodes per group
-	unsigned groups;       // Total number of block groups.
-	unsigned blockbits;    // Bits per block.  (Also blocks per group.)
-
-	// For gene2fs
-	unsigned nextblock;    // Next data block to allocate
-	unsigned nextgroup;    // Next group we'll be allocating from
-	int fsfd;              // File descriptor of filesystem (to output to).
-
-	struct ext2_superblock sb;
-};
-
-struct mkfifo_data {
-	char *mode;
-};
-
-struct netcat_data {
-	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.
-	long port;             // -p Bind to a specific source port.
-	long listen;           // -l Listen for connection instead of dialing out.
-	long wait;             // -w Wait # seconds for a connection.
-	long delay;            // -i delay between lines sent
-};
-
-struct oneit_data {
-	char *console;
-};
-
-struct patch_data {
-	char *infile;
-	long prefix;
-
-	struct double_list *plines, *flines;
-	long oldline, oldlen, newline, newlen, linenum;
-	int context, state, filein, fileout, filepatch;
-	char *tempname, *oldname;
-};
-
-struct sed_data {
-	struct arg_list *commands;
-};
-
-struct sleep_data {
-	long seconds;
-};
-
-struct touch_data {
-	char *ref_file;
-	char *time;
-	long length;
-};
-
-struct toysh_data {
-	char *command;
-};
-
-extern union toy_union {
-	struct dmesg_data dmesg;
-	struct df_data df;
-	struct mke2fs_data mke2fs;
-	struct mkfifo_data mkfifo;
-	struct netcat_data netcat;
-	struct oneit_data oneit;
-	struct patch_data patch;
-	struct sed_data sed;
-	struct sleep_data sleep;
-	struct touch_data touch;
-	struct toysh_data toysh;
-} toy;
-
-#define TOYFLAG_USR      (1<<0)
-#define TOYFLAG_BIN      (1<<1)
-#define TOYFLAG_SBIN     (1<<2)
-#define TOYMASK_LOCATION ((1<<4)-1)
-
-#define TOYFLAG_NOFORK   (1<<4)
-
-extern struct toy_list {
-	char *name;
-	void (*toy_main)(void);
-	char *options;
-	int flags;
-} toy_list[];
--- a/toys/toysh.c	Sat Jan 19 17:55:45 2008 -0600
+++ b/toys/toysh.c	Sun Jan 20 17:25:44 2008 -0600
@@ -170,7 +170,11 @@
 
 #include "toys.h"
 
-#define TT toy.toysh
+DEFINE_GLOBALS(
+	char *command;
+)
+
+#define TT this.toysh
 
 // A single executable, its arguments, and other information we know about it.
 #define TOYSH_FLAG_EXIT    1