[PATCH 07/10] command: remove list_head from struct command

Sascha Hauer s.hauer at pengutronix.de
Sat Mar 9 05:53:08 EST 2013


struct command is statically initialized many times in barebox. The list_head
included in struct command is only needed during runtime, so embed a struct
command_entry into struct command. The static information is included in
struct command_entry whereas the list_head is in struct command. This saves
number of commands * sizeof(struct list_head) bytes from the binary image.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 commands/help.c   |  8 ++++----
 common/command.c  | 41 +++++++++++++++++++++--------------------
 common/complete.c | 12 ++++++------
 common/module.c   |  2 +-
 include/command.h | 23 +++++++++++++++--------
 5 files changed, 47 insertions(+), 39 deletions(-)

diff --git a/commands/help.c b/commands/help.c
index a12d9c3..e3cd1f6 100644
--- a/commands/help.c
+++ b/commands/help.c
@@ -32,13 +32,13 @@ static int do_help(int argc, char *argv[])
 
 	if (argc == 1) {	/* show list of commands */
 		for_each_command(cmdtp)
-			if(strlen(cmdtp->name) > max_length)
-				max_length = strlen(cmdtp->name);
+			if (strlen(cmdtp->entry.name) > max_length)
+				max_length = strlen(cmdtp->entry.name);
 
 		for_each_command(cmdtp) {
-			if (!cmdtp->usage)
+			if (!cmdtp->entry.usage)
 				continue;
-			printf("%*s - %s\n", max_length, cmdtp->name, cmdtp->usage);
+			printf("%*s - %s\n", max_length, cmdtp->entry.name, cmdtp->entry.usage);
 		}
 		return 0;
 	}
diff --git a/common/command.c b/common/command.c
index 7f2b777..59087ef 100644
--- a/common/command.c
+++ b/common/command.c
@@ -38,17 +38,17 @@ void barebox_cmd_usage(struct command *cmdtp)
 {
 #ifdef	CONFIG_LONGHELP
 		/* found - print (long) help info */
-		if (cmdtp->help) {
-			puts (cmdtp->help);
+		if (cmdtp->entry.help) {
+			puts (cmdtp->entry.help);
 		} else {
-			puts (cmdtp->name);
+			puts (cmdtp->entry.name);
 			putchar (' ');
 			puts ("- No help available.\n");
 		}
 		putchar ('\n');
 #else	/* no long help available */
-		if (cmdtp->usage) {
-			puts (cmdtp->usage);
+		if (cmdtp->entry.usage) {
+			puts (cmdtp->entry.usage);
 			puts("\n");
 		}
 #endif	/* CONFIG_LONGHELP */
@@ -57,8 +57,8 @@ EXPORT_SYMBOL(barebox_cmd_usage);
 
 static int compare(struct list_head *a, struct list_head *b)
 {
-	char *na = (char*)list_entry(a, struct command, list)->name;
-	char *nb = (char*)list_entry(b, struct command, list)->name;
+	char *na = (char*)list_entry(a, struct command, list)->entry.name;
+	char *nb = (char*)list_entry(b, struct command, list)->entry.name;
 
 	return strcmp(na, nb);
 }
@@ -74,7 +74,7 @@ int execute_command(int argc, char **argv)
 	/* Look up command in command table */
 	if ((cmdtp = find_cmd(argv[0]))) {
 		/* OK - call function to do the command */
-		ret = cmdtp->cmd(argc, argv);
+		ret = cmdtp->entry.cmd(argc, argv);
 		if (ret == COMMAND_ERROR_USAGE) {
 			barebox_cmd_usage(cmdtp);
 			ret = COMMAND_ERROR;
@@ -93,31 +93,32 @@ int execute_command(int argc, char **argv)
 	return ret;
 }
 
-int register_command(struct command *cmd)
+int register_command(struct command_entry *entry)
 {
+	struct command *cmd = xzalloc(sizeof(*cmd));
+
+	memcpy(&cmd->entry, entry, sizeof(*entry));
+
 	/*
 	 * We do not check if the command already exists.
 	 * This allows us to overwrite a builtin command
 	 * with a module.
 	 */
 
-	debug("register command %s\n", cmd->name);
+	debug("register command %s\n", cmd->entry.name);
 
 	list_add_sort(&cmd->list, &command_list, compare);
 
-	if (cmd->aliases) {
-		char **aliases = (char**)cmd->aliases;
+	if (cmd->entry.aliases) {
+		char **aliases = (char**)cmd->entry.aliases;
 		while(*aliases) {
 			char *usage = "alias for ";
-			struct command *c = xzalloc(sizeof(struct command));
-
-			memcpy(c, cmd, sizeof(struct command));
+			struct command_entry *c = xzalloc(sizeof(*c));
 
+			memcpy(c, entry, sizeof(*entry));
 			c->name = *aliases;
-			c->usage = xmalloc(strlen(usage) + strlen(cmd->name) + 1);
-			sprintf((char*)c->usage, "%s%s", usage, cmd->name);
-
 			c->aliases = NULL;
+			c->usage = asprintf("%s%s", usage, cmd->entry.name);
 
 			register_command(c);
 
@@ -137,7 +138,7 @@ struct command *find_cmd (const char *cmd)
 	struct command *cmdtp;
 
 	for_each_command(cmdtp)
-		if (!strcmp(cmd, cmdtp->name))
+		if (!strcmp(cmd, cmdtp->entry.name))
 			return cmdtp;
 
 	return NULL;	/* not found or ambiguous command */
@@ -152,7 +153,7 @@ EXPORT_SYMBOL(find_cmd);
  */
 static int init_command_list(void)
 {
-	struct command *cmdtp;
+	struct command_entry *cmdtp;
 
 	for (cmdtp = &__barebox_cmd_start;
 			cmdtp != &__barebox_cmd_end;
diff --git a/common/complete.c b/common/complete.c
index 9206ef0..7b6d845 100644
--- a/common/complete.c
+++ b/common/complete.c
@@ -138,10 +138,10 @@ int command_complete(struct string_list *sl, char *instr)
 		instr = "";
 
 	for_each_command(cmdtp) {
-		if (strncmp(instr, cmdtp->name, strlen(instr)))
+		if (strncmp(instr, cmdtp->entry.name, strlen(instr)))
 			continue;
 
-		string_list_add_asprintf(sl, "%s ", cmdtp->name);
+		string_list_add_asprintf(sl, "%s ", cmdtp->entry.name);
 	}
 
 	return 0;
@@ -279,11 +279,11 @@ static char* cmd_complete_lookup(struct string_list *sl, char *instr)
 	char *res = NULL;
 
 	for_each_command(cmdtp) {
-		len = strlen(cmdtp->name);
-		if (!strncmp(instr, cmdtp->name, len) && instr[len] == ' ') {
+		len = strlen(cmdtp->entry.name);
+		if (!strncmp(instr, cmdtp->entry.name, len) && instr[len] == ' ') {
 			instr += len + 1;
-			if (cmdtp->complete) {
-				ret = cmdtp->complete(sl, instr);
+			if (cmdtp->entry.complete) {
+				ret = cmdtp->entry.complete(sl, instr);
 				res = instr;
 			}
 			goto end;
diff --git a/common/module.c b/common/module.c
index 109fe5c..639ee61 100644
--- a/common/module.c
+++ b/common/module.c
@@ -293,7 +293,7 @@ struct module * load_module(void *mod_image, unsigned long len)
 
 	cmdindex = find_sec(ehdr, sechdrs, secstrings, ".barebox_cmd");
 	if (cmdindex) {
-		struct command *cmd =(struct command *)sechdrs[cmdindex].sh_addr;
+		struct command_entry *cmd =(struct command_entry *)sechdrs[cmdindex].sh_addr;
 		for (i = 0; i < sechdrs[cmdindex].sh_size / sizeof(struct command); i++) {
 			register_command(cmd);
 			cmd++;
diff --git a/include/command.h b/include/command.h
index ffc722c..b774ae6 100644
--- a/include/command.h
+++ b/include/command.h
@@ -41,7 +41,7 @@ struct string_list;
 /*
  * Monitor Command Table
  */
-struct command {
+struct command_entry {
 	const char	*name;		/* Command Name			*/
 	const char	**aliases;
 					/* Implementation function	*/
@@ -49,9 +49,8 @@ struct command {
 	int		(*complete)(struct string_list *sl, char *instr);
 	const char	*usage;		/* Usage message	(short)	*/
 
-	struct list_head list;		/* List of commands		*/
 #ifdef	CONFIG_LONGHELP
-	const char	*help;		/* Help  message	(long)	*/
+	const char	*help;			/* Help  message	(long)	*/
 #endif
 }
 #ifdef __x86_64__
@@ -60,9 +59,17 @@ __attribute__((aligned(64)))
 #endif
 ;
 
-extern struct command __barebox_cmd_start;
-extern struct command __barebox_cmd_end;
+/*
+ * Monitor Command Table
+ */
+struct command {
+	struct command_entry entry;
+
+	struct list_head list;		/* List of commands		*/
+};
 
+extern struct command_entry __barebox_cmd_start;
+extern struct command_entry __barebox_cmd_end;
 
 /* common/command.c */
 struct command *find_cmd(const char *cmd);
@@ -80,8 +87,8 @@ void barebox_cmd_usage(struct command *cmdtp);
 #define Struct_Section  __attribute__ ((unused,section (".barebox_cmd")))
 
 #define BAREBOX_CMD_START(_name)							\
-extern const struct command __barebox_cmd_##_name;					\
-const struct command __barebox_cmd_##_name						\
+extern const struct command_entry __barebox_cmd_##_name;				\
+const struct command_entry __barebox_cmd_##_name					\
 	__attribute__ ((unused,section (".barebox_cmd_" __stringify(_name)))) = {	\
 	.name		= #_name,
 
@@ -110,6 +117,6 @@ static const __maybe_unused char cmd_##_name##_help[] =
 
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
-int register_command(struct command *);
+int register_command(struct command_entry *);
 
 #endif	/* __COMMAND_H */
-- 
1.8.2.rc2




More information about the barebox mailing list