basename: implement -a and -s SUFFIX
function old new delta basename_main 145 207 +62 packed_usage 33914 33950 +36 .rodata 104241 104250 +9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 107/0) Total: 107 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		| @@ -29,9 +29,11 @@ | ||||
| /* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */ | ||||
|  | ||||
| //usage:#define basename_trivial_usage | ||||
| //usage:       "FILE [SUFFIX]" | ||||
| //usage:       "FILE [SUFFIX] | -a FILE... | -s SUFFIX FILE..." | ||||
| //usage:#define basename_full_usage "\n\n" | ||||
| //usage:       "Strip directory path and .SUFFIX from FILE" | ||||
| //usage:       "Strip directory path and SUFFIX from FILE\n" | ||||
| //usage:     "\n	-a		All arguments are FILEs" | ||||
| //usage:     "\n	-s SUFFIX	Remove SUFFIX (implies -a)" | ||||
| //usage: | ||||
| //usage:#define basename_example_usage | ||||
| //usage:       "$ basename /usr/local/bin/foo\n" | ||||
| @@ -48,31 +50,43 @@ | ||||
| int basename_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||||
| int basename_main(int argc UNUSED_PARAM, char **argv) | ||||
| { | ||||
| 	size_t m, n; | ||||
| 	char *s; | ||||
| 	unsigned opts; | ||||
| 	const char *suffix = NULL; | ||||
|  | ||||
| 	if (argv[1] && strcmp(argv[1], "--") == 0) { | ||||
| 		argv++; | ||||
| 	} | ||||
| 	if (!argv[1]) | ||||
| 		bb_show_usage(); | ||||
| 	/* '+': stop at first non-option */ | ||||
| 	opts = getopt32(argv, "^+" "as:" | ||||
| 		"\0" "-1" /* At least one argument */ | ||||
| 		, &suffix | ||||
| 	); | ||||
| 	argv += optind; | ||||
|  | ||||
| 	/* It should strip slash: /abc/def/ -> def */ | ||||
| 	s = bb_get_last_path_component_strip(*++argv); | ||||
| 	do { | ||||
| 		char *s; | ||||
| 		size_t m; | ||||
|  | ||||
| 	m = strlen(s); | ||||
| 	if (*++argv) { | ||||
| 		if (argv[1]) | ||||
| 			bb_show_usage(); | ||||
| 		n = strlen(*argv); | ||||
| 		if ((m > n) && (strcmp(s+m-n, *argv) == 0)) { | ||||
| 			m -= n; | ||||
| 			/*s[m] = '\0'; - redundant */ | ||||
| 		/* It should strip slash: /abc/def/ -> def */ | ||||
| 		s = bb_get_last_path_component_strip(*argv++); | ||||
| 		m = strlen(s); | ||||
| 		if (!opts) { | ||||
| 			if (*argv) { | ||||
| 				suffix = *argv; | ||||
| 				if (argv[1]) | ||||
| 					bb_show_usage(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 		if (suffix) { | ||||
| 			size_t n = strlen(suffix); | ||||
| 			if ((m > n) && (strcmp(s + m - n, suffix) == 0)) { | ||||
| 				m -= n; | ||||
| 				/*s[m] = '\0'; - redundant */ | ||||
| 			} | ||||
| 		} | ||||
| 		/* puts(s) will do, but we can do without stdio this way: */ | ||||
| 		s[m++] = '\n'; | ||||
| 		/* NB: != is correct here: */ | ||||
| 		if (full_write(STDOUT_FILENO, s, m) != (ssize_t)m) | ||||
| 			return EXIT_FAILURE; | ||||
| 	} while (opts && *argv); | ||||
|  | ||||
| 	/* puts(s) will do, but we can do without stdio this way: */ | ||||
| 	s[m++] = '\n'; | ||||
| 	/* NB: != is correct here: */ | ||||
| 	return full_write(STDOUT_FILENO, s, m) != (ssize_t)m; | ||||
| 	return EXIT_SUCCESS; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user