# HG changeset patch # User Samuel Holland # Date 1396566104 18000 # Node ID 0d295a46f853224c03aa923fd982b60b9a604558 # Parent 9a13e6637d7b87a4464166e0f8a2b3d417c74534 Here is a basic implementation of fold[0]. It does not support multibyte characters, though that would probably just require more switch cases. diff -r 9a13e6637d7b -r 0d295a46f853 toys/pending/fold.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toys/pending/fold.c Thu Apr 03 18:01:44 2014 -0500 @@ -0,0 +1,93 @@ +/* fold.c - fold text + * + * Copyright 2014 Samuel Holland + * + * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/fold.html + +USE_FOLD(NEWTOY(fold, "bsw#", TOYFLAG_USR|TOYFLAG_BIN)) + +config FOLD + bool "fold" + default n + help + usage: fold [-bs] [-w WIDTH] [FILE...] + + Folds/wraps FILE or stdin at 80 columns. + + -b Wrap based on bytes instead of columns + -s Wrap at farthest right whitespace + -w Wrap at WIDTH columns instead of 80 +*/ + +#define FOR_fold +#include "toys.h" + +GLOBALS( + int w_number; +) + +void do_fold(int fd, char *name) +{ + int buflen, i, len = 0, split; + int max = (toys.optflags & FLAG_w) ? TT.w_number : 80; + char tmp, *buf; + + if (max > sizeof(toybuf)) { + error_exit("width (%ld) too big", max); + } + + while (read(fd, toybuf, sizeof(toybuf))) { + split = -1; + buf = toybuf; + buflen = strlen(buf); + + for (i = 0; i < buflen; i++) { + switch (buf[i]) { + case '\n': + //reset len, FLAG_b or not; just print multiple lines at once + len = 0; + continue; + case '\b': + //len cannot be negative; not allowed to wrap after backspace + if (toys.optflags & FLAG_b) len++; + else if (len > 0) len--; + continue; + case '\r': + //not allowed to wrap after carriage return + if (toys.optflags & FLAG_b) len++; + else len = 0; + continue; + case '\t': + //round to 8, but we add one after falling through + //(because of whitespace, but it also takes care of FLAG_b) + if (!(toys.optflags & FLAG_b)) len = (len & -8) + 7; + case ' ': + split = i; + default: + len++; + } + + //we don't want to double up \n; not allowed to wrap before \b + if (len >= max && buf[i+1] != '\n' && buf[i+1] != '\b') { + if (!(toys.optflags & FLAG_s)) split = i; //we split right here + tmp = buf[split+1]; + buf[split+1] = 0; + xprintf("%s\n", buf); + buf[split+1] = tmp; + len = 0; + if (split < buflen - 1) { + buf += split + 1; + i = 0; + buflen = strlen(buf); + } + } + } + + xputs(buf); + } +} + +void fold_main(void) +{ + loopfiles(toys.optargs, do_fold); +}