cut: stop using static data. This alone removed ~70 bytes of code. + some optimizations
No binary (build failed)
—
(log yok)
| @@ -33,11 +33,6 @@ enum { | |
| NON_RANGE = -1 | |
| }; | |
| - | /* growable array holding a series of lists */ |
| - | static struct cut_list *cut_lists; |
| - | static unsigned int nlists; /* number of elements in above list */ |
| - | |
| - | |
| static int cmpfunc(const void *a, const void *b) | |
| { | |
| return (((struct cut_list *) a)->startpos - | |
| @@ -45,18 +40,19 @@ static int cmpfunc(const void *a, const void *b) | |
| } | |
| - | static void cut_file(FILE *file, char delim) |
| + | static void cut_file(FILE *file, char delim, const struct cut_list *cut_lists, unsigned nlists) |
| { | |
| - | char *line = NULL; |
| - | unsigned int linenum = 0; /* keep these zero-based to be consistent */ |
| + | char *line; |
| + | unsigned linenum = 0; /* keep these zero-based to be consistent */ |
| /* go through every line in the file */ | |
| while ((line = xmalloc_fgetline(file)) != NULL) { | |
| /* set up a list so we can keep track of what's been printed */ | |
| - | char * printed = xzalloc(strlen(line) * sizeof(char)); |
| - | char * orig_line = line; |
| - | unsigned int cl_pos = 0; |
| + | int linelen = strlen(line); |
| + | char *printed = xzalloc(linelen * sizeof(char)); |
| + | char *orig_line = line; |
| + | unsigned cl_pos = 0; |
| int spos; | |
| /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ | |
| @@ -64,15 +60,19 @@ static void cut_file(FILE *file, char delim) | |
| /* print the chars specified in each cut list */ | |
| for (; cl_pos < nlists; cl_pos++) { | |
| spos = cut_lists[cl_pos].startpos; | |
| - | while (spos < (int)strlen(line)) { |
| + | while (spos < linelen) { |
| if (!printed[spos]) { | |
| printed[spos] = 'X'; | |
| putchar(line[spos]); | |
| } | |
| spos++; | |
| if (spos > cut_lists[cl_pos].endpos | |
| - | || cut_lists[cl_pos].endpos == NON_RANGE) |
| + | /* NON_RANGE is -1, so if below is true, |
| + | * the above was true too (spos is >= 0) */ |
| + | /* || cut_lists[cl_pos].endpos == NON_RANGE */ |
| + | ) { |
| break; | |
| + | } |
| } | |
| } | |
| } else if (delim == '\n') { /* cut by lines */ | |
| @@ -89,7 +89,8 @@ static void cut_file(FILE *file, char delim) | |
| spos++; | |
| /* go to the next list if we're at the end of this one */ | |
| if (spos > cut_lists[cl_pos].endpos | |
| - | || cut_lists[cl_pos].endpos == NON_RANGE) { |
| + | || cut_lists[cl_pos].endpos == NON_RANGE |
| + | ) { |
| cl_pos++; | |
| /* get out if there's no more lists to process */ | |
| if (cl_pos >= nlists) | |
| @@ -148,7 +149,7 @@ static void cut_file(FILE *file, char delim) | |
| * this is a list, and we're not at the end of that | |
| * list */ | |
| } while (spos <= cut_lists[cl_pos].endpos && line | |
| - | && cut_lists[cl_pos].endpos != NON_RANGE); |
| + | && cut_lists[cl_pos].endpos != NON_RANGE); |
| } | |
| } | |
| /* if we printed anything at all, we need to finish it with a | |
| @@ -164,17 +165,21 @@ static void cut_file(FILE *file, char delim) | |
| int cut_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int cut_main(int argc UNUSED_PARAM, char **argv) | |
| { | |
| + | /* growable array holding a series of lists */ |
| + | struct cut_list *cut_lists = NULL; |
| + | unsigned nlists = 0; /* number of elements in above list */ |
| char delim = '\t'; /* delimiter, default is tab */ | |
| char *sopt, *ltok; | |
| + | unsigned opt; |
| opt_complementary = "b--bcf:c--bcf:f--bcf"; | |
| - | getopt32(argv, optstring, &sopt, &sopt, &sopt, <ok); |
| + | opt = getopt32(argv, optstring, &sopt, &sopt, &sopt, <ok); |
| // argc -= optind; | |
| argv += optind; | |
| - | if (!(option_mask32 & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS))) |
| + | if (!(opt & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS))) |
| bb_error_msg_and_die("expected a list of bytes, characters, or fields"); | |
| - | if (option_mask32 & CUT_OPT_DELIM_FLGS) { |
| + | if (opt & CUT_OPT_DELIM_FLGS) { |
| if (ltok[0] && ltok[1]) { /* more than 1 char? */ | |
| bb_error_msg_and_die("the delimiter must be a single character"); | |
| } | |
| @@ -182,10 +187,10 @@ int cut_main(int argc UNUSED_PARAM, char **argv) | |
| } | |
| /* non-field (char or byte) cutting has some special handling */ | |
| - | if (!(option_mask32 & CUT_OPT_FIELDS_FLGS)) { |
| + | if (!(opt & CUT_OPT_FIELDS_FLGS)) { |
| static const char _op_on_field[] ALIGN1 = " only when operating on fields"; | |
| - | if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) { |
| + | if (opt & CUT_OPT_SUPPRESS_FLGS) { |
| bb_error_msg_and_die | |
| ("suppressing non-delimited lines makes sense%s", | |
| _op_on_field); | |
| @@ -231,8 +236,8 @@ int cut_main(int argc UNUSED_PARAM, char **argv) | |
| e = EOL; | |
| } else { | |
| e = xatoi_u(ltok); | |
| - | /* if the user specified and end position of 0, that means "til the |
| - | * end of the line */ |
| + | /* if the user specified and end position of 0, |
| + | * that means "til the end of the line" */ |
| if (e == 0) | |
| e = EOL; | |
| e--; /* again, arrays are zero based, lines are 1 based */ | |
| @@ -242,6 +247,8 @@ int cut_main(int argc UNUSED_PARAM, char **argv) | |
| /* add the new list */ | |
| cut_lists = xrealloc_vector(cut_lists, 4, nlists); | |
| + | /* NB: startpos is always >= 0, |
| + | * while endpos may be = NON_RANGE (-1) */ |
| cut_lists[nlists].startpos = s; | |
| cut_lists[nlists].endpos = e; | |
| nlists++; | |
| @@ -269,7 +276,7 @@ int cut_main(int argc UNUSED_PARAM, char **argv) | |
| retval = EXIT_FAILURE; | |
| continue; | |
| } | |
| - | cut_file(file, delim); |
| + | cut_file(file, delim, cut_lists, nlists); |
| fclose_if_not_stdin(file); | |
| } while (*++argv); | |