1/* fmt.c - Text formatter 2 * 3 * Copyright 2017 The Android Open Source Project 4 * 5 * Deviations from original: 6 * we treat all whitespace as equal (no tab expansion, no runs of spaces) 7 * we don't try to recognize ends of sentences to double-space after ./?/! 8 9USE_FMT(NEWTOY(fmt, "w#", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE)) 10 11config FMT 12 bool "fmt" 13 default y 14 help 15 usage: fmt [-w WIDTH] [FILE...] 16 17 Reformat input to not exceed a maximum line length. 18 19 -w WIDTH maximum characters per line (default 75) 20*/ 21 22#define FOR_fmt 23#include "toys.h" 24 25GLOBALS( 26 int width; 27) 28 29static void do_fmt(int fd, char *name) 30{ 31 FILE *fp = xfdopen(fd, "re"); 32 char *line = NULL; 33 size_t allocated_length = 0; 34 int cols = 0, is_first = 1, indent_end = 0, line_length; 35 36 while ((line_length = getline(&line, &allocated_length, fp)) > 0) { 37 int b = 0, e, w; 38 39 while (b < line_length && isspace(line[b])) b++; 40 if (b == line_length) { 41 if (cols > 0) xputc('\n'); 42 xputc('\n'); 43 is_first = 1; 44 cols = 0; 45 continue; 46 } 47 if (is_first) indent_end = b; 48 49 for (; b < line_length; b = e + 1) { 50 while (isspace(line[b])) b++; 51 for (e = b + 1; e < line_length && !isspace(line[e]);) e++; 52 if (e >= line_length) break; 53 54 line[e] = 0; 55 w = utf8len(line + b); 56 57 if (!is_first && (cols + (is_first?indent_end:1) + w) >= TT.width) { 58 xputc('\n'); 59 is_first = 1; 60 cols = 0; 61 } 62 xprintf("%.*s%.*s",is_first?indent_end:1,is_first?line:" ",(e-b),line+b); 63 cols += (is_first?indent_end:1) + w; 64 b = e + 1; 65 is_first = 0; 66 } 67 } 68 if (cols > 0) xputc('\n'); 69 fclose(fp); 70} 71 72void fmt_main(void) 73{ 74 if (TT.width < 0) error_exit("negative width: %d", TT.width); 75 if (!TT.width) TT.width = 75; 76 77 loopfiles(toys.optargs, do_fmt); 78} 79