From 547c8d980bb5ae37f8002aead4e155cc5554dfca Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Thu, 3 Apr 2014 18:01:44 -0500 Subject: Here is a basic implementation of fold[0]. It does not support multibyte characters, though that would probably just require more switch cases. --- toys/pending/fold.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 toys/pending/fold.c (limited to 'toys/pending/fold.c') diff --git a/toys/pending/fold.c b/toys/pending/fold.c new file mode 100644 index 00000000..0d6719b0 --- /dev/null +++ b/toys/pending/fold.c @@ -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); +} -- cgit v1.2.3