[PATCH] debloat lash by 4.803725881571%

Bernhard Fischer rep.nop at aon.at
Thu Jun 15 21:03:56 UTC 2006


Hi,

The attached patch (which is only very lightly tested so far) does shave
some bloat off lash:

   text	   data	    bss	    dec	    hex	filename
   7288	    168	     59	   7515	   1d5b	shell/lash.o.orig
   6927	    168	     59	   7154	   1bf2	shell/lash.o

1) I'm not entirely sure that i got the bb_skip_whitespace stuff right,
   would be nice if someone could eye these for a second.
2) Also i'm not sure if we want to put this into the repo just now or if
   we should wait for the 1.2 release-branch to be created and
   eventually apply it afterwards. I'll leave the decision whether to
   apply it for 1.2.0 or not to the maintainer..

TIA for taking the time to look over it and for making comments.
-------------- next part --------------
Index: shell/lash.c
===================================================================
--- shell/lash.c	(revision 15395)
+++ shell/lash.c	(working copy)
@@ -165,7 +165,7 @@
 
 /* Globals that are static to this file */
 static const char *cwd;
-static char *local_pending_command = NULL;
+static char *local_pending_command;
 static struct jobset job_list = { NULL, NULL };
 static int argc;
 static char **argv;
@@ -187,7 +187,7 @@
 	va_end(args);
 }
 #else
-static inline void debug_printf(const char *format, ...) { }
+static inline void debug_printf(const char ATTRIBUTE_UNUSED *format, ...) { }
 #endif
 
 /*
@@ -228,7 +228,7 @@
 	else
 		newdir = child->argv[1];
 	if (chdir(newdir)) {
-		printf("cd: %s: %m\n", newdir);
+		bb_perror_msg("cd: %s", newdir);
 		return EXIT_FAILURE;
 	}
 	cwd = xgetcwd((char *)cwd);
@@ -315,12 +315,12 @@
 }
 
 /* built-in 'help' handler */
-static int builtin_help(struct child_prog *dummy)
+static int builtin_help(struct child_prog ATTRIBUTE_UNUSED *dummy)
 {
 	struct built_in_command *x;
 
-	printf("\nBuilt-in commands:\n");
-	printf("-------------------\n");
+	printf("\nBuilt-in commands:\n"
+		   "-------------------\n");
 	for (x = bltins; x->cmd; x++) {
 		if (x->descr==NULL)
 			continue;
@@ -331,7 +331,7 @@
 			continue;
 		printf("%s\t%s\n", x->cmd, x->descr);
 	}
-	printf("\n\n");
+	putchar('\n');
 	return EXIT_SUCCESS;
 }
 
@@ -354,7 +354,7 @@
 
 
 /* built-in 'pwd' handler */
-static int builtin_pwd(struct child_prog *dummy)
+static int builtin_pwd(struct child_prog ATTRIBUTE_UNUSED *dummy)
 {
 	cwd = xgetcwd((char *)cwd);
 	if (!cwd)
@@ -378,7 +378,7 @@
 	}
 	res = putenv(v);
 	if (res)
-		fprintf(stderr, "export: %m\n");
+		bb_perror_msg("export");
 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
 	if (strncmp(v, "PS1=", 4)==0)
 		PS1 = getenv("PS1");
@@ -397,7 +397,7 @@
 /* built-in 'read VAR' handler */
 static int builtin_read(struct child_prog *child)
 {
-	int res = 0, len, newlen;
+	int res = 0, len;
 	char *s;
 	char string[MAX_READ];
 
@@ -408,19 +408,19 @@
 		string[len++] = '=';
 		string[len]   = '\0';
 		fgets(&string[len], sizeof(string) - len, stdin);	/* read string */
-		newlen = strlen(string);
-		if(newlen > len)
-			string[--newlen] = '\0';	/* chomp trailing newline */
+		res = strlen(string);
+		if (res > len)
+			string[--res] = '\0';	/* chomp trailing newline */
 		/*
 		** string should now contain "VAR=<value>"
 		** copy it (putenv() won't do that, so we must make sure
 		** the string resides in a static buffer!)
 		*/
 		res = -1;
-		if((s = strdup(string)))
+		if ((s = strdup(string)))
 			res = putenv(s);
 		if (res)
-			fprintf(stderr, "read: %m\n");
+			bb_perror_msg("read");
 	}
 	else
 		fgets(string, sizeof(string), stdin);
@@ -435,16 +435,12 @@
 	int status;
 	int fd;
 
-	if (child->argv[1] == NULL)
-		return EXIT_FAILURE;
-
-	input = fopen(child->argv[1], "r");
+	input = bb_wfopen(child->argv[1], "r");
 	if (!input) {
-		printf( "Couldn't open file '%s'\n", child->argv[1]);
 		return EXIT_FAILURE;
 	}
 
-	fd=fileno(input);
+	fd = fileno(input);
 	llist_add_to(&close_me_list, (void *)fd);
 	/* Now run the file */
 	status = busy_loop(input);
@@ -548,7 +544,7 @@
 
 #if 0
 			/* Printing this stuff is a pain, since it tends to
-			 * overwrite the prompt an inconveinient moments.  So
+			 * overwrite the prompt at inconvenient moments.  So
 			 * don't do that.  */
 			if (job->stopped_progs == job->num_progs) {
 				printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
@@ -658,7 +654,7 @@
 	if (shell_context == 0) {
 		free(PS1);
 		PS1=xmalloc(strlen(cwd)+4);
-		sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ?  "$ ":"# ");
+		sprintf(PS1, "%s %c ", cwd, ( geteuid() != 0 ) ? '$': '#');
 		*prompt_str = PS1;
 	} else {
 		*prompt_str = PS2;
@@ -731,20 +727,18 @@
 
 static char * strsep_space( char *string, int * ix)
 {
-	char *token;
-
 	/* Short circuit the trivial case */
 	if ( !string || ! string[*ix])
 		return NULL;
 
 	/* Find the end of the token. */
-	while( string[*ix] && !isspace(string[*ix]) ) {
+	while (string[*ix] && !isspace(string[*ix]) ) {
 		(*ix)++;
 	}
 
 	/* Find the end of any whitespace trailing behind
 	 * the token and let that be part of the token */
-	while( string[*ix] && isspace(string[*ix]) ) {
+	while (string[*ix] && (isspace)(string[*ix]) ) {
 		(*ix)++;
 	}
 
@@ -753,9 +747,7 @@
 		return NULL;
 	}
 
-	token = bb_xstrndup(string, *ix);
-
-	return token;
+	return bb_xstrndup(string, *ix);
 }
 
 static int expand_arguments(char *command)
@@ -764,7 +756,7 @@
 	expand_t expand_result;
 	char *tmpcmd, *cmd, *cmd_copy;
 	char *src, *dst, *var;
-	const char *out_of_space = "out of space during expansion";
+	const char * const out_of_space = "out of space during expansion";
 	int flags = GLOB_NOCHECK
 #ifdef GLOB_BRACE
 		| GLOB_BRACE
@@ -889,7 +881,7 @@
 				num_skip_chars=1;
 			} else {
 				src=dst+1;
-				while(isalnum(*src) || *src=='_') src++;
+				while((isalnum)(*src) || *src=='_') src++;
 			}
 			if (src == NULL) {
 				src = dst+dstlen;
@@ -933,10 +925,11 @@
 	char *command;
 	char *return_command = NULL;
 	char *src, *buf;
-	int argc_l = 0;
-	int done = 0;
+	int argc_l;
+	int flag;
+#define DONE (1)
+#define SAW_QUOTE (2)
 	int argv_alloced;
-	int saw_quote = 0;
 	char quote = '\0';
 	struct child_prog *prog;
 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
@@ -945,8 +938,7 @@
 #endif
 
 	/* skip leading white space */
-	while (**command_ptr && isspace(**command_ptr))
-		(*command_ptr)++;
+	*command_ptr = (char*)bb_skip_whitespace(*command_ptr);
 
 	/* this handles empty lines or leading '#' characters */
 	if (!**command_ptr || (**command_ptr == '#')) {
@@ -980,9 +972,10 @@
 	prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
 	prog->argv[0] = job->cmdbuf;
 
+	flag = argc_l = 0;
 	buf = command;
 	src = *command_ptr;
-	while (*src && !done) {
+	while (*src && !(flag & DONE)) {
 		if (quote == *src) {
 			quote = '\0';
 		} else if (quote) {
@@ -1003,7 +996,7 @@
 					   *src == ']') *buf++ = '\\';
 			*buf++ = *src;
 		} else if (isspace(*src)) {
-			if (*prog->argv[argc_l] || saw_quote) {
+			if (*prog->argv[argc_l] || flag & SAW_QUOTE) {
 				buf++, argc_l++;
 				/* +1 here leaves room for the NULL which ends argv */
 				if ((argc_l + 1) == argv_alloced) {
@@ -1013,21 +1006,21 @@
 										  argv_alloced);
 				}
 				prog->argv[argc_l] = buf;
-				saw_quote = 0;
+				flag ^= SAW_QUOTE;
 			}
 		} else
 			switch (*src) {
 			case '"':
 			case '\'':
 				quote = *src;
-				saw_quote = 1;
+				flag |= SAW_QUOTE;
 				break;
 
 			case '#':			/* comment */
 				if (*(src-1)== '$')
 					*buf++ = *src;
 				else
-					done = 1;
+					flag |= DONE;
 				break;
 
 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
@@ -1070,8 +1063,7 @@
 
 				/* This isn't POSIX sh compliant. Oh well. */
 				chptr = src;
-				while (isspace(*chptr))
-					chptr++;
+				chptr = (char*)bb_skip_whitespace(chptr);
 
 				if (!*chptr) {
 					bb_error_msg("file name expected after %c", *(src-1));
@@ -1090,13 +1082,10 @@
 
 			case '|':			/* pipe */
 				/* finish this command */
-				if (*prog->argv[argc_l] || saw_quote)
+				if (*prog->argv[argc_l] || flag & SAW_QUOTE)
 					argc_l++;
 				if (!argc_l) {
-					bb_error_msg("empty command in pipe");
-					free_job(job);
-					job->num_progs=0;
-					return 1;
+					goto empty_command_in_pipe;
 				}
 				prog->argv[argc_l] = NULL;
 
@@ -1116,10 +1105,10 @@
 				prog->argv[0] = ++buf;
 
 				src++;
-				while (*src && isspace(*src))
-					src++;
+				src = (char*)bb_skip_whitespace(src);
 
 				if (!*src) {
+empty_command_in_pipe:
 					bb_error_msg("empty command in pipe");
 					free_job(job);
 					job->num_progs=0;
@@ -1133,9 +1122,10 @@
 #ifdef CONFIG_LASH_JOB_CONTROL
 			case '&':			/* background */
 				*inbg = 1;
+				/* fallthrough */
 #endif
 			case ';':			/* multiple commands */
-				done = 1;
+				flag |= DONE;
 				return_command = *command_ptr + (src - *command_ptr) + 1;
 				break;
 
@@ -1156,7 +1146,7 @@
 		src++;
 	}
 
-	if (*prog->argv[argc_l] || saw_quote) {
+	if (*prog->argv[argc_l] || flag & SAW_QUOTE) {
 		argc_l++;
 	}
 	if (!argc_l) {
@@ -1175,6 +1165,8 @@
 	*command_ptr = return_command;
 
 	return 0;
+#undef DONE
+#undef SAW_QUOTE
 }
 
 /* Run the child_prog, no matter what kind of command it uses.
@@ -1233,7 +1225,7 @@
 
 	/* Do not use bb_perror_msg_and_die() here, since we must not
 	 * call exit() but should call _exit() instead */
-	fprintf(stderr, "%s: %m\n", child->argv[0]);
+	bb_perror_msg("%s", child->argv[0]);
 	_exit(EXIT_FAILURE);
 }
 
@@ -1338,7 +1330,7 @@
 			signal(SIGTTOU, SIG_DFL);
 			signal(SIGCHLD, SIG_DFL);
 
-			// Close all open filehandles.
+			/* Close all open filehandles. */
 			while(close_me_list) close((int)llist_pop(&close_me_list));
 
 			if (outpipe[1]!=-1) {
@@ -1553,14 +1545,13 @@
 
 int lash_main(int argc_l, char **argv_l)
 {
-	int opt, interactive=FALSE;
+	unsigned long opt;
 	FILE *input = stdin;
 	argc = argc_l;
 	argv = argv_l;
 
 	/* These variables need re-initializing when recursing */
 	last_jobid = 0;
-	local_pending_command = NULL;
 	close_me_list = NULL;
 	job_list.head = NULL;
 	job_list.fg = NULL;
@@ -1573,27 +1564,18 @@
 			llist_add_to(&close_me_list, (void *)fileno(prof_input));
 			/* Now run the file */
 			busy_loop(prof_input);
-			fclose(prof_input);
+			bb_fclose_nonstdin(prof_input);
 			llist_pop(&close_me_list);
 		}
 	}
 
-	while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
-		switch (opt) {
-			case 'c':
-				input = NULL;
-				if (local_pending_command != 0)
-					bb_error_msg_and_die("multiple -c arguments");
-				local_pending_command = bb_xstrdup(argv[optind]);
-				optind++;
-				argv = argv+optind;
-				break;
-			case 'i':
-				interactive = TRUE;
-				break;
-			default:
-				bb_show_usage();
-		}
+	opt = bb_getopt_ulflags(argc_l, argv_l, "+ic:", &local_pending_command);
+#define LASH_OPT_i (1)
+#define LASH_OPT_c (2)
+	if (opt & LASH_OPT_c) {
+		input = NULL;
+		optind++;
+		argv += optind;
 	}
 	/* A shell is interactive if the `-i' flag was given, or if all of
 	 * the following conditions are met:
@@ -1604,15 +1586,15 @@
 	 *    Refer to Posix.2, the description of the `sh' utility. */
 	if (argv[optind]==NULL && input==stdin &&
 			isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
-		interactive=TRUE;
+		opt |= LASH_OPT_i;
 	}
 	setup_job_control();
-	if (interactive==TRUE) {
+	if (opt & LASH_OPT_i) {
 		//printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
 		/* Looks like they want an interactive shell */
 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
-		printf( "\n\n%s Built-in shell (lash)\n", BB_BANNER);
-		printf( "Enter 'help' for a list of built-in commands.\n\n");
+		printf("\n\n%s Built-in shell (lash)\n"
+			   "Enter 'help' for a list of built-in commands.\n\n", BB_BANNER);
 #endif
 	} else if (local_pending_command==NULL) {
 		//printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);


More information about the busybox mailing list