morpheus-base

morpheus base system
git clone git://git.2f30.org/morpheus-base
Log | Files | Refs

fold.c (1755B)


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