cut: add proper stdout error handling, fix "-" handling;

modest code shrink
This commit is contained in:
Denis Vlasenko 2007-11-23 07:26:15 +00:00
parent e85dbae389
commit 3831c91c95

View File

@ -16,13 +16,11 @@
/* option vars */
static const char optstring[] ALIGN1 = "b:c:f:d:sn";
#define CUT_OPT_BYTE_FLGS (1<<0)
#define CUT_OPT_CHAR_FLGS (1<<1)
#define CUT_OPT_FIELDS_FLGS (1<<2)
#define CUT_OPT_DELIM_FLGS (1<<3)
#define CUT_OPT_SUPPRESS_FLGS (1<<4)
static char delim = '\t'; /* delimiter, default is tab */
#define CUT_OPT_BYTE_FLGS (1 << 0)
#define CUT_OPT_CHAR_FLGS (1 << 1)
#define CUT_OPT_FIELDS_FLGS (1 << 2)
#define CUT_OPT_DELIM_FLGS (1 << 3)
#define CUT_OPT_SUPPRESS_FLGS (1 << 4)
struct cut_list {
int startpos;
@ -47,7 +45,7 @@ static int cmpfunc(const void *a, const void *b)
}
static void cut_file(FILE * file)
static void cut_file(FILE *file, char delim)
{
char *line = NULL;
unsigned int linenum = 0; /* keep these zero-based to be consistent */
@ -163,11 +161,10 @@ static void cut_file(FILE * file)
}
}
static const char _op_on_field[] ALIGN1 = " only when operating on fields";
int cut_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int cut_main(int argc, char **argv)
{
char delim = '\t'; /* delimiter, default is tab */
char *sopt, *ltok;
opt_complementary = "b--bcf:c--bcf:f--bcf";
@ -178,7 +175,7 @@ int cut_main(int argc, char **argv)
bb_error_msg_and_die("expected a list of bytes, characters, or fields");
if (option_mask32 & CUT_OPT_DELIM_FLGS) {
if (strlen(ltok) > 1) {
if (ltok[0] && ltok[1]) { /* more than 1 char? */
bb_error_msg_and_die("the delimiter must be a single character");
}
delim = ltok[0];
@ -186,6 +183,8 @@ int cut_main(int argc, char **argv)
/* non-field (char or byte) cutting has some special handling */
if (!(option_mask32 & CUT_OPT_FIELDS_FLGS)) {
static const char _op_on_field[] ALIGN1 = " only when operating on fields";
if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) {
bb_error_msg_and_die
("suppressing non-delimited lines makes sense%s",
@ -210,15 +209,12 @@ int cut_main(int argc, char **argv)
while ((ltok = strsep(&sopt, ",")) != NULL) {
/* it's actually legal to pass an empty list */
if (strlen(ltok) == 0)
if (!ltok[0])
continue;
/* get the start pos */
ntok = strsep(&ltok, "-");
if (ntok == NULL) {
bb_error_msg
("internal error: ntok is null for start pos!?\n");
} else if (strlen(ntok) == 0) {
if (!ntok[0]) {
s = BOL;
} else {
s = xatoi_u(ntok);
@ -229,13 +225,12 @@ int cut_main(int argc, char **argv)
}
/* get the end pos */
ntok = strsep(&ltok, "-");
if (ntok == NULL) {
if (ltok == NULL) {
e = NON_RANGE;
} else if (strlen(ntok) == 0) {
} else if (!ltok[0]) {
e = EOL;
} else {
e = xatoi_u(ntok);
e = xatoi_u(ltok);
/* if the user specified and end position of 0, that means "til the
* end of the line */
if (e == 0)
@ -245,11 +240,6 @@ int cut_main(int argc, char **argv)
e = NON_RANGE;
}
/* if there's something left to tokenize, the user passed
* an invalid list */
if (ltok)
bb_error_msg_and_die("invalid byte or field list");
/* add the new list */
cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
cut_lists[nlists-1].startpos = s;
@ -266,23 +256,31 @@ int cut_main(int argc, char **argv)
qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
}
/* argv[0..argc-1] should be names of file to process. If no
* files were specified or '-' was specified, take input from stdin.
* Otherwise, we process all the files specified. */
if (argv[0] == NULL || LONE_DASH(argv[0])) {
cut_file(stdin);
} else {
FILE *file;
{
int retval = EXIT_SUCCESS;
FILE *file = stdin;
if (!*argv) {
argv--;
goto jump_in;
}
do {
file = fopen_or_warn(argv[0], "r");
if (file) {
cut_file(file);
fclose(file);
file = stdin;
if (NOT_LONE_DASH(*argv))
file = fopen_or_warn(*argv, "r");
if (!file) {
retval = EXIT_FAILURE;
continue;
}
jump_in:
cut_file(file, delim);
if (NOT_LONE_DASH(*argv))
fclose(file);
} while (*++argv);
if (ENABLE_FEATURE_CLEAN_UP)
free(cut_lists);
fflush_stdout_and_exit(retval);
}
if (ENABLE_FEATURE_CLEAN_UP)
free(cut_lists);
return EXIT_SUCCESS;
}