aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Holland <samuel@sholland.net>2014-04-03 18:01:44 -0500
committerSamuel Holland <samuel@sholland.net>2014-04-03 18:01:44 -0500
commit547c8d980bb5ae37f8002aead4e155cc5554dfca (patch)
tree3eb8655cb862c03f23d0b0ee745875862e8a0e7a
parent7183a637432c9f0957e4e0e68b71e61a67fa89d6 (diff)
downloadtoybox-547c8d980bb5ae37f8002aead4e155cc5554dfca.tar.gz
Here is a basic implementation of fold[0]. It does not support multibyte characters, though that would probably just require more switch cases.
-rw-r--r--toys/pending/fold.c93
1 files changed, 93 insertions, 0 deletions
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 <samuel@sholland.net>
+ *
+ * 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);
+}