-/* $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 $ */
/*
#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 <ctype.h>
+#include <err.h>
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
/*
* fmt -- format the concatenation of input files or standard input
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;
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--;
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();
* 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) {
/*
* 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);
}
* 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;
*/
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++)
* attached at the end. Pass these words along to the output
* line packer.
*/
+void
split(line)
char line[];
{
/*
* Collect a 'word,' allowing it to contain escaped white
- * space.
+ * space.
*/
while (*cp && *cp != ' ') {
if (*cp == '\\' && isspace(cp[1]))
/*
* Guarantee a space at end of line. Two spaces after end of
- * sentence punctuation.
+ * sentence punctuation.
*/
if (*cp == '\0') {
*cp2++ = ' ';
*cp2++ = *cp++;
*cp2 = '\0';
/*
- * LIZ@UOM 6/18/85 pack(word);
+ * LIZ@UOM 6/18/85 pack(word);
*/
pack(word, wordl);
}
/*
* Initialize the output section.
*/
+void
setout()
{
outp = NOSTR;
* pack(word)
* char word[];
*/
-pack(word,wl)
+void
+pack(word, wl)
char word[];
int 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;
* its way. Set outp to NOSTR to indicate the absence of the current
* line prefix.
*/
+void
oflush()
{
if (outp == NOSTR)
* Take the passed line buffer, insert leading tabs where possible, and
* output on standard output (finally).
*/
+void
tabulate(line)
char line[];
{
while (cp >= line && *cp == ' ')
cp--;
*++cp = '\0';
-
+
/*
* Count the leading blank space and tabulate.
*/
* Initialize the output line with the appropriate number of
* leading blanks.
*/
+void
leadin()
{
register int b;
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;
{