From 3e58ca64035d5246d85fd45dfbda7025aa9a1156 Mon Sep 17 00:00:00 2001 From: millert Date: Sun, 26 Jan 1997 03:56:52 +0000 Subject: [PATCH] Dynamic buffering to handle arbitrary line length and center option from FreeBSD I also cleaned it up to pass -Wall and check malloc(). --- usr.bin/fmt/fmt.c | 157 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 38 deletions(-) diff --git a/usr.bin/fmt/fmt.c b/usr.bin/fmt/fmt.c index 86e5d453f6c..0d04381515e 100644 --- a/usr.bin/fmt/fmt.c +++ b/usr.bin/fmt/fmt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fmt.c,v 1.3 1997/01/17 07:12:35 millert Exp $ */ +/* $OpenBSD: fmt.c,v 1.4 1997/01/26 03:56:52 millert Exp $ */ /* $NetBSD: fmt.c,v 1.4 1995/09/01 01:29:41 jtc Exp $ */ /* @@ -43,14 +43,17 @@ static char copyright[] = #ifndef lint #if 0 static char sccsid[] = "@(#)fmt.c 8.1 (Berkeley) 7/20/93"; +#else +static char rcsid[] = "$OpenBSD: fmt.c,v 1.4 1997/01/26 03:56:52 millert Exp $"; #endif -static char rcsid[] = "$OpenBSD: fmt.c,v 1.3 1997/01/17 07:12:35 millert Exp $"; #endif /* not lint */ +#include +#include +#include #include #include #include -#include /* * fmt -- format the concatenation of input files or standard input @@ -74,15 +77,29 @@ int max_length; /* Max line length in output */ int pfx; /* Current leading blank count */ int lineno; /* Current input line */ int mark; /* Last place we saw a head line */ +int center; /* Did they ask to center lines? */ char *headnames[] = {"To", "Subject", "Cc", 0}; +void fmt __P((FILE *)); +void setout __P((void)); +void prefix __P((char *)); +void split __P((char *)); +void pack __P((char *, int)); +void oflush __P((void)); +void tabulate __P((char *)); +void leadin __P((void)); +char *savestr __P((char *)); +int ispref __P((char *, char *)); +int ishead __P((char *)); + /* * Drive the whole formatter by managing input files. Also, * cause initialization of the output stuff and flush it out * at the end. */ +int main(argc, argv) int argc; char **argv; @@ -91,14 +108,21 @@ main(argc, argv) register int errs = 0; int number; /* LIZ@UOM 6/18/85 */ + (void) setlocale(LC_CTYPE, ""); + goal_length = GOAL_LENGTH; max_length = MAX_LENGTH; setout(); lineno = 1; mark = -10; /* - * LIZ@UOM 6/18/85 -- Check for goal and max length arguments + * LIZ@UOM 6/18/85 -- Check for goal and max length arguments */ + if (argc > 1 && !strcmp(argv[1], "-c")) { + center++; + argc--; + argv++; + } if (argc > 1 && (1 == (sscanf(argv[1], "%d", &number)))) { argv++; argc--; @@ -109,11 +133,9 @@ main(argc, argv) max_length = number; } } - if (max_length <= goal_length) { - fprintf(stderr, "Max length must be greater than %s\n", - "goal length"); - exit(1); - } + if (max_length <= goal_length) + errx(1, "Max length (%d) must be greater than goal length: %d", + max_length, goal_length); if (argc < 2) { fmt(stdin); oflush(); @@ -137,13 +159,38 @@ main(argc, argv) * doing ^H processing, expanding tabs, stripping trailing blanks, * and sending each line down for analysis. */ +void fmt(fi) FILE *fi; { - char linebuf[BUFSIZ], canonb[BUFSIZ]; - register char *cp, *cp2; + static char *linebuf = 0, *canonb = 0; + register char *cp, *cp2, cc; register int c, col; - +#define CHUNKSIZE 1024 + static int lbufsize = 0, cbufsize = 0; + + if (center) { + if ((linebuf = malloc(BUFSIZ)) == NOSTR) + errx(1, "Ran out of memory"); + for (;;) { + cp = fgets(linebuf, BUFSIZ, fi); + if (!cp) + return; + while (*cp && isspace(*cp)) + cp++; + cp2 = cp + strlen(cp) - 1; + while (cp2 > cp && isspace(*cp2)) + cp2--; + if (cp == cp2) + putchar('\n'); + col = cp2 - cp; + for (c = 0; c < (goal_length-col)/2; c++) + putchar(' '); + while (cp <= cp2) + putchar(*cp++); + putchar('\n'); + } + } c = getc(fi); while (c != EOF) { /* @@ -151,44 +198,73 @@ fmt(fi) * Leave tabs for now. */ cp = linebuf; - while (c != '\n' && c != EOF && cp-linebuf < BUFSIZ-1) { + while (c != '\n' && c != EOF) { + if (cp - linebuf >= lbufsize) { + int offset = cp - linebuf; + lbufsize += CHUNKSIZE; + linebuf = realloc(linebuf, lbufsize); + if(linebuf == 0) + abort(); + cp = linebuf + offset; + } if (c == '\b') { if (cp > linebuf) cp--; c = getc(fi); continue; } - if ((c < ' ' || c >= 0177) && c != '\t') { + if (!isprint(c) && c != '\t') { c = getc(fi); continue; } *cp++ = c; c = getc(fi); } - *cp = '\0'; /* * Toss anything remaining on the input line. */ while (c != '\n' && c != EOF) c = getc(fi); - + + if (cp != NULL) { + *cp = '\0'; + } else { + putchar('\n'); + c = getc(fi); + continue; + } + /* * Expand tabs on the way to canonb. */ col = 0; cp = linebuf; cp2 = canonb; - while (c = *cp++) { - if (c != '\t') { + while ((cc = *cp++)) { + if (cc != '\t') { col++; - if (cp2-canonb < BUFSIZ-1) - *cp2++ = c; + if (cp2 - canonb >= cbufsize) { + int offset = cp2 - canonb; + cbufsize += CHUNKSIZE; + canonb = realloc(canonb, cbufsize); + if(canonb == 0) + abort(); + cp2 = canonb + offset; + } + *cp2++ = cc; continue; } do { - if (cp2-canonb < BUFSIZ-1) - *cp2++ = ' '; + if (cp2 - canonb >= cbufsize) { + int offset = cp2 - canonb; + cbufsize += CHUNKSIZE; + canonb = realloc(canonb, cbufsize); + if(canonb == 0) + abort(); + cp2 = canonb + offset; + } + *cp2++ = ' '; col++; } while ((col & 07) != 0); } @@ -212,13 +288,14 @@ fmt(fi) * Finally, if the line minus the prefix is a mail header, try to keep * it on a line by itself. */ +void prefix(line) char line[]; { register char *cp, **hp; register int np, h; - if (strlen(line) == 0) { + if (*line == '\0') { oflush(); putchar('\n'); return; @@ -233,7 +310,7 @@ prefix(line) */ if (np != pfx && (np > pfx || abs(pfx-np) > 8)) oflush(); - if (h = ishead(cp)) + if ((h = ishead(cp))) oflush(), mark = lineno; if (lineno - mark < 3 && lineno - mark > 0) for (hp = &headnames[0]; *hp != (char *) 0; hp++) @@ -259,6 +336,7 @@ prefix(line) * attached at the end. Pass these words along to the output * line packer. */ +void split(line) char line[]; { @@ -273,7 +351,7 @@ split(line) /* * Collect a 'word,' allowing it to contain escaped white - * space. + * space. */ while (*cp && *cp != ' ') { if (*cp == '\\' && isspace(cp[1])) @@ -284,7 +362,7 @@ split(line) /* * Guarantee a space at end of line. Two spaces after end of - * sentence punctuation. + * sentence punctuation. */ if (*cp == '\0') { *cp2++ = ' '; @@ -295,7 +373,7 @@ split(line) *cp2++ = *cp++; *cp2 = '\0'; /* - * LIZ@UOM 6/18/85 pack(word); + * LIZ@UOM 6/18/85 pack(word); */ pack(word, wordl); } @@ -316,6 +394,7 @@ char *outp; /* Pointer in above */ /* * Initialize the output section. */ +void setout() { outp = NOSTR; @@ -341,7 +420,8 @@ setout() * pack(word) * char word[]; */ -pack(word,wl) +void +pack(word, wl) char word[]; int wl; { @@ -355,14 +435,14 @@ pack(word,wl) * length of the line before the word is added; t is now the length * of the line after the word is added * t = strlen(word); - * if (t+s <= LENGTH) + * if (t+s <= LENGTH) */ s = outp - outbuf; t = wl + s; if ((t <= goal_length) || ((t <= max_length) && (t - goal_length <= goal_length - s))) { /* - * In like flint! + * In like flint! */ for (cp = word; *cp; *outp++ = *cp++); return; @@ -379,6 +459,7 @@ pack(word,wl) * its way. Set outp to NOSTR to indicate the absence of the current * line prefix. */ +void oflush() { if (outp == NOSTR) @@ -392,6 +473,7 @@ oflush() * Take the passed line buffer, insert leading tabs where possible, and * output on standard output (finally). */ +void tabulate(line) char line[]; { @@ -405,7 +487,7 @@ tabulate(line) while (cp >= line && *cp == ' ') cp--; *++cp = '\0'; - + /* * Count the leading blank space and tabulate. */ @@ -431,6 +513,7 @@ tabulate(line) * Initialize the output line with the appropriate number of * leading blanks. */ +void leadin() { register int b; @@ -450,20 +533,18 @@ char * savestr(str) char str[]; { - register char *top; + char *top; - top = malloc(strlen(str) + 1); - if (top == NOSTR) { - fprintf(stderr, "fmt: Ran out of memory\n"); - exit(1); - } - strcpy(top, str); + top = strdup(str); + if (top == NOSTR) + errx(1, "Ran out of memory"); return (top); } /* * Is s1 a prefix of s2?? */ +int ispref(s1, s2) register char *s1, *s2; { -- 2.20.1