sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

fold.c (2225B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <ctype.h>
      3 #include <stdint.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 
      8 #include "text.h"
      9 #include "util.h"
     10 
     11 static int    bflag = 0;
     12 static int    sflag = 0;
     13 static size_t width = 80;
     14 
     15 static void
     16 foldline(struct line *l) {
     17 	size_t i, col, last, spacesect, len;
     18 
     19 	for (i = 0, last = 0, col = 0, spacesect = 0; i < l->len; i++) {
     20 		if (!UTF8_POINT(l->data[i]) && !bflag)
     21 			continue;
     22 		if (col >= width) {
     23 			len = ((sflag && spacesect) ? spacesect : i) - last;
     24 			if (fwrite(l->data + last, 1, len, stdout) != len)
     25 				eprintf("fwrite <stdout>:");
     26 			putchar('\n');
     27 			last = (sflag && spacesect) ? spacesect : i;
     28 			col = 0;
     29 			spacesect = 0;
     30 		}
     31 		if (sflag && isspace(l->data[i]))
     32 			spacesect = i + 1;
     33 		if (!bflag && iscntrl(l->data[i])) {
     34 			switch(l->data[i]) {
     35 			case '\b':
     36 				col -= (col > 0);
     37 				break;
     38 			case '\r':
     39 				col = 0;
     40 				break;
     41 			case '\t':
     42 				col += (col + 1) % 8;
     43 				break;
     44 			}
     45 		} else {
     46 			col++;
     47 		}
     48 	}
     49 	if (l->len - last)
     50 		fwrite(l->data + last, 1, l->len - last, stdout);
     51 }
     52 
     53 static void
     54 fold(FILE *fp, const char *fname)
     55 {
     56 	static struct line line;
     57 	static size_t size = 0;
     58 	ssize_t len;
     59 
     60 	while ((len = getline(&line.data, &size, fp)) > 0) {
     61 		line.len = len;
     62 		foldline(&line);
     63 	}
     64 	if (ferror(fp))
     65 		eprintf("getline %s:", fname);
     66 }
     67 
     68 static void
     69 usage(void)
     70 {
     71 	eprintf("usage: %s [-bs] [-w num | -num] [FILE ...]\n", argv0);
     72 }
     73 
     74 int
     75 main(int argc, char *argv[])
     76 {
     77 	FILE *fp;
     78 	int ret = 0;
     79 
     80 	ARGBEGIN {
     81 	case 'b':
     82 		bflag = 1;
     83 		break;
     84 	case 's':
     85 		sflag = 1;
     86 		break;
     87 	case 'w':
     88 		width = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE_MAX));
     89 		break;
     90 	ARGNUM:
     91 		if (!(width = ARGNUMF()))
     92 			eprintf("illegal width value, too small\n");
     93 		break;
     94 	default:
     95 		usage();
     96 	} ARGEND
     97 
     98 	if (!argc) {
     99 		fold(stdin, "<stdin>");
    100 	} else {
    101 		for (; *argv; argc--, argv++) {
    102 			if (!strcmp(*argv, "-")) {
    103 				*argv = "<stdin>";
    104 				fp = stdin;
    105 			} else if (!(fp = fopen(*argv, "r"))) {
    106 				weprintf("fopen %s:", *argv);
    107 				ret = 1;
    108 				continue;
    109 			}
    110 			fold(fp, *argv);
    111 			if (fp != stdin && fshut(fp, *argv))
    112 				ret = 1;
    113 		}
    114 	}
    115 
    116 	ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
    117 
    118 	return ret;
    119 }