diff options
Diffstat (limited to 'toys/posix/cut.c')
-rw-r--r-- | toys/posix/cut.c | 166 |
1 files changed, 64 insertions, 102 deletions
diff --git a/toys/posix/cut.c b/toys/posix/cut.c index 6f813102..abf944de 100644 --- a/toys/posix/cut.c +++ b/toys/posix/cut.c @@ -3,8 +3,8 @@ * Copyright 2012 Ranjan Kumar <ranjankumar.bth@gmail.com>, Kyungwan Han <asura321@gamil.com> * * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html - * -USE_CUT(NEWTOY(cut, "b:c:f:d:sn", TOYFLAG_BIN)) + +USE_CUT(NEWTOY(cut, "b:|c:|f:|d:sn[!cbf]", TOYFLAG_BIN)) config CUT bool "cut" @@ -26,7 +26,7 @@ typedef struct _slist { int start_position; int end_position; struct _slist *next; -}SLIST; +} SLIST; GLOBALS( char *delim; @@ -37,11 +37,6 @@ GLOBALS( unsigned nelem; ) -#define BEGINOFLINE 0 -#define ENDOFLINE INT_MAX -#define NORANGE -1 - -static int get_user_options(void); void (*do_cut)(int); static void do_fcut(int fd); static void do_bccut(int fd); @@ -64,8 +59,7 @@ static void add_to_list(int start, int end) if (head_ref == NULL || (head_ref)->start_position >= start) { temp1_node->next = head_ref; head_ref = temp1_node; - } - else { + } else { /* Locate the node before the point of insertion */ current = head_ref; while (current->next!=NULL && current->next->start_position < temp1_node->start_position) @@ -74,41 +68,37 @@ static void add_to_list(int start, int end) current->next = temp1_node; } TT.slist_head = head_ref; - return; } -/* - * parse list and add to slist. - */ +// parse list and add to slist. static void parse_list(char *list) { - char *ctoken, *dtoken; - int start = 0, end = 0; - while((ctoken = strsep(&list, ",")) != NULL) { - if(!ctoken[0]) continue; + for (;;) { + char *ctoken = strsep(&list, ","), *dtoken; + int start = 0, end = INT_MAX; + + if (!ctoken) break; + if (!*ctoken) continue; //Get start position. - dtoken = strsep(&ctoken, "-"); - if(!dtoken[0]) start = BEGINOFLINE; - else { + if (*(dtoken = strsep(&ctoken, "-"))) { start = get_int_value(dtoken, 0, INT_MAX); start = (start?(start-1):start); } + //Get end position. - if(ctoken == NULL) end = NORANGE; //case e.g. 1,2,3 - else if(!ctoken[0]) end = ENDOFLINE; //case e.g. N- - else {//case e.g. N-M + if (!ctoken) end = -1; //case e.g. 1,2,3 + else if (*ctoken) {//case e.g. N-M end = get_int_value(ctoken, 0, INT_MAX); - end = (end?end:ENDOFLINE); - end--; - if(end == start) end = NORANGE; + if (!end) end = INT_MAX; + end--; + if(end == start) end = -1; } add_to_list(start, end); TT.nelem++; } //if list is missing in command line. - if(TT.nelem == 0) error_exit("missing positions list:"); - return; + if (!TT.nelem) error_exit("missing positions list"); } /* @@ -134,78 +124,68 @@ static void get_data(void) } } } - return; } -/* - * cut main function. -*/ void cut_main(void) { char delimiter = '\t'; //default delimiter. - int num_of_options = 0; char *list; TT.nelem = 0; TT.slist_head = NULL; - //verify the number of options provided by user. - num_of_options = get_user_options(); - if(num_of_options == 0) error_exit("specify a list of bytes, characters, or fields"); - else if(num_of_options > 1) error_exit("only one type of list may be specified"); //Get list and assign the function. - if(toys.optflags & FLAG_f) { + if (toys.optflags & FLAG_f) { list = TT.flist; do_cut = do_fcut; - } - else if(toys.optflags & FLAG_c) { + } else if (toys.optflags & FLAG_c) { list = TT.clist; do_cut = do_bccut; - } - else { + } else { list = TT.blist; do_cut = do_bccut; } - if(toys.optflags & FLAG_d) { + 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"); + if(TT.delim[0] && TT.delim[1]) + perror_exit("the delimiter must be a single character"); delimiter = TT.delim[0]; } if(!(toys.optflags & FLAG_d) && (toys.optflags & FLAG_f)) { - TT.delim = (char *)xzalloc(2); + 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)) { + 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"); } parse_list(list); get_data(); - if(!(toys.optflags & FLAG_d) && (toys.optflags & FLAG_f)) { + if (!(toys.optflags & FLAG_d) && (toys.optflags & FLAG_f)) { free(TT.delim); TT.delim = NULL; } free_list(); - return; } -/* - * perform cut operation on the given delimiter. - */ +// perform cut operation on the given delimiter. static void do_fcut(int fd) { char *buff; char *delimiter = TT.delim; - while((buff = get_line(fd)) != NULL) { + + while ((buff = get_line(fd))) { //does line have any delimiter?. - if(strrchr(buff, (int)delimiter[0]) == NULL) { + if (strrchr(buff, (int)delimiter[0]) == NULL) { //if not then print whole line and move to next line. - if(!(toys.optflags & FLAG_s)) xputs(buff); + if (!(toys.optflags & FLAG_s)) xputs(buff); continue; } @@ -215,34 +195,33 @@ static void do_fcut(int fd) char *pfield = xzalloc(strlen(buff) + 1); SLIST *temp_node = TT.slist_head; - if(temp_node != NULL) { + if (temp_node != NULL) { //process list on each line. - while(cpos < TT.nelem && buff) { - if(!temp_node) break; + while (cpos < TT.nelem && buff) { + if (!temp_node) break; start = temp_node->start_position; do { char *field = NULL; //count number of delimeters per line. - while(buff) { - if(ndelimiters < start) { + while (buff) { + if (ndelimiters < start) { ndelimiters++; field = strsep(&buff, delimiter); - } - else break; + } else break; } //print field (if not yet printed). - if(!pfield[ndelimiters]) { - if(ndelimiters == start) { + if (!pfield[ndelimiters]) { + if (ndelimiters == start) { //put delimiter. - if(nprinted_fields++ > 0) xputc(delimiter[0]); - if(field) fputs(field, stdout); + if (nprinted_fields++ > 0) xputc(delimiter[0]); + 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_position == NORANGE) || (!buff)) break; - }while(start <= temp_node->end_position); + if ((temp_node->end_position < 0) || (!buff)) break; + } while(start <= temp_node->end_position); temp_node = temp_node->next; cpos++; } @@ -251,38 +230,37 @@ static void do_fcut(int fd) free(pfield); pfield = NULL; }//End of while loop. - return; } -/* - * perform cut operation char or byte. - */ +// perform cut operation char or byte. static void do_bccut(int fd) { char *buff; - while((buff = get_line(fd)) != NULL) { + + while ((buff = get_line(fd)) != NULL) { unsigned cpos = 0; int buffln = strlen(buff); char *pfield = xzalloc(buffln + 1); SLIST *temp_node = TT.slist_head; - if(temp_node != NULL) { - while(cpos < TT.nelem) { + + if (temp_node != NULL) { + while (cpos < TT.nelem) { int start; - if(!temp_node) break; + + if (!temp_node) break; start = temp_node->start_position; - while(start < buffln) { + while (start < buffln) { //to avoid duplicate field printing. - if(pfield[start]) { - if(++start <= temp_node->end_position) continue; + if (pfield[start]) { + if (++start <= temp_node->end_position) continue; temp_node = temp_node->next; break; - } - else { + } else { //make sure this field won't print again. pfield[start] = (char) 0x23; //put some char at this position. xputc(buff[start]); } - if(++start > temp_node->end_position) { + if (++start > temp_node->end_position) { temp_node = temp_node->next; break; } @@ -294,22 +272,6 @@ static void do_bccut(int fd) free(pfield); pfield = NULL; } - return; -} - -/* - * used to verify "c", "b" and "f" options are present in command line. - * As cut command can only except any of them at a time. -*/ -static int get_user_options(void) -{ - int i = 3, flag = 0; - for(; i<6; i++) {//verify 3rd, 4th and 5th bit is set. - int mask = 1; - mask = mask << i; - if(toys.optflags & mask) flag++; - } - return flag; } /* @@ -318,10 +280,10 @@ static int get_user_options(void) static void free_list(void) { SLIST *temp; - while(TT.slist_head != NULL) { + + while (TT.slist_head != NULL) { temp = TT.slist_head->next; free(TT.slist_head); TT.slist_head = temp; } - return; } |