/* * fold.c * Implementation of SUSv3 XCU fold utility * Copyright © 2007 Rich Felker * Licensed under the terms of the GNU General Public License, v2 or later */ #include #include #include #include #include #include #include #include #include #include static void my_perror(char *prog, char *msg) { char *err = strerror(errno); write(2, prog, strlen(prog)); write(2, ": ", 2); write(2, msg, strlen(msg)); write(2, ": ", 2); write(2, err, strlen(err)); write(2, "\n", 1); } int main(int argc, char *argv[]) { int b; char *name; char dummy[MB_LEN_MAX]; size_t i, j, len=127; wchar_t wc, *buf = malloc(sizeof wc * len); long col, out_col, width=80; int w; int splitable; int byte=0, space=0; FILE *f; if (!setlocale(LC_CTYPE, "")) my_perror(argv[0], "setlocale"); while ((b = getopt(argc, argv, "bsw:")) != EOF) switch(b) { case 'b': byte=1; break; case 's': space=1; break; case 'w': width=strtoul(optarg, NULL, 10); break; default: return 1; } if (optind == argc) { f = stdin; name = "-"; goto nofiles; } while (optind < argc) { f = fopen(name=argv[optind++], "rb"); if (!f) { my_perror(argv[0], name); continue; } nofiles: i = col = out_col = 0; splitable = -1; while ((wc = getwc(f))>=0) { if (i == len) { buf = realloc(buf, sizeof wc * (len=len<<1|1)); if (!buf) { my_perror(argv[0], "realloc"); return 1; } } buf[i++] = wc; if (wc == '\n') { col = 0; splitable = -1; goto output; } else if (byte) w = wctomb(dummy, wc); else if (wc == '\t') { w = 8-(col&7); if (w > width - col) w = 8; } else if (wc == '\r') col = w = 0; else if (wc == '\b') { if (col) col--; w = 0; } else w = wcwidth(wc); if (col && w > width - col) { if (putwchar('\n')==WEOF) goto werr; col -= out_col; splitable = -1; } col += w; if (space && iswblank(wc)) splitable = 1; if (splitable) { output: for (j=0; j>= 1; } } if (ferror(f)) my_perror(argv[0], name); if (f != stdin) fclose(f); } return 0; werr: my_perror(argv[0], "write error"); return 1; }