cut: add proper stdout error handling, fix "-" handling;
modest code shrink
diff --git a/coreutils/cut.c b/coreutils/cut.c
index 257f3d6..4f0bed3 100644
--- a/coreutils/cut.c
+++ b/coreutils/cut.c
@@ -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 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 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 @@
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 @@
/* 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 @@
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(<ok, "-");
- 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 @@
}
/* get the end pos */
- ntok = strsep(<ok, "-");
- 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 @@
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 @@
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;
}