[Toybox] [PATCH 1/2] Cleanup pass on cut.
Daniel K. Levy
alliedenvy at gmail.com
Sat Aug 29 18:09:59 PDT 2015
Cleanup pass on cut.
Move -sbc and -dbc exclusivity checks into args parsing.
Use loopfiles instead of get_data reimplementation.
Behavioral change: parse_list now doesn't allow empty specifiers,
a zero start, or end less than start.
Minor additional cleanups.
---
toys/posix/cut.c | 142 +++++++++++++++----------------------------------------
1 file changed, 38 insertions(+), 104 deletions(-)
diff --git a/toys/posix/cut.c b/toys/posix/cut.c
index bb2b22d..934e27f 100644
--- a/toys/posix/cut.c
+++ b/toys/posix/cut.c
@@ -7,7 +7,7 @@
*
* TODO: cleanup
-USE_CUT(NEWTOY(cut, "b:|c:|f:|d:sn[!cbf]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_CUT(NEWTOY(cut, "b:|c:|f:|d:sn[!cbf][!dbc][!sbc]", TOYFLAG_USR|TOYFLAG_BIN))
config CUT
bool "cut"
@@ -21,7 +21,7 @@ config CUT
-c LIST select only these characters from LIST.
-f LIST select only these fields.
-d DELIM use DELIM instead of TAB for field delimiter.
- -s do not print lines not containing delimiters.
+ -s only print lines containing delimiters.
-n don't split multibyte characters (Ignored).
*/
#define FOR_cut
@@ -35,7 +35,7 @@ GLOBALS(
void *slist_head;
unsigned nelem;
- void (*do_cut)(int fd);
+ void (*do_cut)(int, char *);
)
struct slist {
@@ -45,26 +45,24 @@ struct slist {
static void add_to_list(int start, int end)
{
- struct slist *current, *head_ref, *temp1_node;
+ struct slist *current, *temp1_node;
- head_ref = TT.slist_head;
temp1_node = xzalloc(sizeof(struct slist));
temp1_node->start = start;
temp1_node->end = end;
/* Special case for the head end */
- if (!head_ref || head_ref->start >= start) {
- temp1_node->next = head_ref;
- head_ref = temp1_node;
+ if (!TT.slist_head || ((struct slist*)TT.slist_head)->start >= start) {
+ temp1_node->next = TT.slist_head;
+ TT.slist_head = temp1_node;
} else {
/* Locate the node before the point of insertion */
- current = head_ref;
+ current = TT.slist_head;
while (current->next && current->next->start < temp1_node->start)
current = current->next;
temp1_node->next = current->next;
current->next = temp1_node;
}
- TT.slist_head = head_ref;
}
// parse list and add to slist.
@@ -75,22 +73,20 @@ static void parse_list(char *list)
int start = 0, end = INT_MAX;
if (!ctoken) break;
- if (!*ctoken) continue;
+ if (!*ctoken) error_exit("empty position specifier");
//Get start position.
- if (*(dtoken = strsep(&ctoken, "-"))) {
- start = atolx_range(dtoken, 0, INT_MAX);
- start = (start?(start-1):start);
- }
+ if (*(dtoken = strsep(&ctoken, "-")))
+ start = atolx_range(dtoken, 1, INT_MAX)-1;
//Get end position.
if (!ctoken) end = -1; //case e.g. 1,2,3
else if (*ctoken) {//case e.g. N-M
- end = atolx_range(ctoken, 0, INT_MAX);
- if (!end) end = INT_MAX;
- end--;
+ end = atolx_range(ctoken, start+1, INT_MAX)-1;
if(end == start) end = -1;
- }
+ } else if (!*dtoken)
+ error_exit("empty position specifier");
+
add_to_list(start, end);
TT.nelem++;
}
@@ -98,49 +94,18 @@ static void parse_list(char *list)
if (!TT.nelem) error_exit("missing positions list");
}
-/*
- * retrive data from the file/s.
- */
-static void get_data(void)
-{
- char **argv = toys.optargs; //file name.
- toys.exitval = EXIT_SUCCESS;
-
- if(!*argv) TT.do_cut(0); //for stdin
- else {
- for(; *argv; ++argv) {
- if(strcmp(*argv, "-") == 0) TT.do_cut(0); //for stdin
- else {
- int fd = open(*argv, O_RDONLY, 0);
- if(fd < 0) {//if file not present then continue with other files.
- perror_msg("%s", *argv);
- continue;
- }
- TT.do_cut(fd);
- xclose(fd);
- }
- }
- }
-}
-
// perform cut operation on the given delimiter.
-static void do_fcut(int fd)
+static void do_fcut(int fd, char *name)
{
- char *buff, *pfield = 0, *delimiter = TT.delim;
+ char *buff, *pfield;
- for (;;) {
- unsigned cpos = 0;
- int start, ndelimiters = -1;
- int nprinted_fields = 0;
+ while ((buff = get_line(fd))) {
+ unsigned cpos;
+ int start, ndelimiters = -1, nprinted_fields = 0;
struct slist *temp_node = TT.slist_head;
- free(pfield);
- pfield = 0;
-
- if (!(buff = get_line(fd))) break;
-
//does line have any delimiter?.
- if (strrchr(buff, (int)delimiter[0]) == NULL) {
+ if (!strchr(buff, *TT.delim)) {
//if not then print whole line and move to next line.
if (!(toys.optflags & FLAG_s)) xputs(buff);
continue;
@@ -148,58 +113,49 @@ static void do_fcut(int fd)
pfield = xzalloc(strlen(buff) + 1);
- if (temp_node) {
//process list on each line.
- while (cpos < TT.nelem && buff) {
- if (!temp_node) break;
+ for (cpos = 0; temp_node && cpos < TT.nelem && buff; cpos++) {
start = temp_node->start;
do {
char *field = 0;
//count number of delimeters per line.
- while (buff) {
- if (ndelimiters < start) {
+ while (buff && ndelimiters < start) {
ndelimiters++;
- field = strsep(&buff, delimiter);
- } else break;
+ field = strsep(&buff, TT.delim);
}
//print field (if not yet printed).
- if (!pfield[ndelimiters]) {
- if (ndelimiters == start) {
+ if (!pfield[ndelimiters] && ndelimiters == start) {
//put delimiter.
- if (nprinted_fields++ > 0) xputc(delimiter[0]);
+ if (nprinted_fields++ > 0) xputc(*TT.delim);
if (field) fputs(field, stdout);
//make sure this field won't print again.
pfield[ndelimiters] = (char) 0x23; //put some char at this position.
- }
}
start++;
if ((temp_node->end < 0) || !buff) break;
} while(start <= temp_node->end);
temp_node = temp_node->next;
- cpos++;
}
- }
xputc('\n');
+ free(pfield);
}
}
// perform cut operation char or byte.
-static void do_bccut(int fd)
+static void do_bccut(int fd, char *name)
{
char *buff;
- while ((buff = get_line(fd)) != NULL) {
- unsigned cpos = 0;
- int buffln = strlen(buff);
+ while ((buff = get_line(fd))) {
+ unsigned cpos;
+ size_t buffln = strlen(buff);
char *pfield = xzalloc(buffln + 1);
struct slist *temp_node = TT.slist_head;
- if (temp_node != NULL) {
- while (cpos < TT.nelem) {
+ for (cpos = 0; temp_node && cpos < TT.nelem; cpos++) {
int start;
- if (!temp_node) break;
start = temp_node->start;
while (start < buffln) {
//to avoid duplicate field printing.
@@ -217,24 +173,19 @@ static void do_bccut(int fd)
break;
}
}
- cpos++;
}
xputc('\n');
- }
free(pfield);
- pfield = NULL;
}
}
void cut_main(void)
{
- char delimiter = '\t'; //default delimiter.
char *list;
TT.nelem = 0;
TT.slist_head = NULL;
- //Get list and assign the function.
if (toys.optflags & FLAG_f) {
list = TT.flist;
TT.do_cut = do_fcut;
@@ -247,30 +198,13 @@ void cut_main(void)
}
if (toys.optflags & FLAG_d) {
- //delimiter must be 1 char.
- if(TT.delim[0] && TT.delim[1])
- perror_exit("the delimiter must be a single character");
- delimiter = TT.delim[0];
- }
+ if (TT.delim[0] && TT.delim[1]) perror_exit("bad -d: need one character");
+ } else TT.delim = "\t";
- if(!(toys.optflags & FLAG_d) && (toys.optflags & FLAG_f)) {
- TT.delim = xzalloc(2);
- TT.delim[0] = delimiter;
- }
-
- //when field is not specified, cutting has some special handling.
- if (!(toys.optflags & FLAG_f)) {
- if (toys.optflags & FLAG_s)
- perror_exit("suppressing non-delimited lines operating on fields");
- if (delimiter != '\t')
- perror_exit("an input delimiter may be specified only when operating on fields");
- }
+ if (!(toys.optflags & FLAG_f) && toys.optflags & FLAG_s)
+ perror_exit("-s needs -f");
parse_list(list);
- get_data();
- if (!(toys.optflags & FLAG_d) && (toys.optflags & FLAG_f)) {
- free(TT.delim);
- TT.delim = NULL;
- }
- llist_traverse(TT.slist_head, free);
+ loopfiles(toys.optargs, TT.do_cut);
+ if (CFG_TOYBOX_FREE) llist_traverse(TT.slist_head, free);
}
---
1440896999.0
More information about the Toybox
mailing list