fmt.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1992-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
static const char usage[] =
"[-?\n@(#)$Id: fmt (AT&T Research) 2007-01-02 $\n]"
"[+NAME?fmt - simple text formatter]"
"[+DESCRIPTION?\bfmt\b reads the input files and left justifies space "
"separated words into lines \awidth\a characters or less in length and "
"writes the lines to the standard output. The standard input is read if "
"\b-\b or no files are specified. Blank lines and interword spacing are "
"preserved in the output. Indentation is preserved, and lines with "
"identical indentation are joined and justified.]"
"[+?\bfmt\b is meant to format mail messages prior to sending, but may "
"also be useful for other simple tasks. For example, in \bvi\b(1) the "
"command \b:!}fmt\b will justify the lines in the current paragraph.]"
"[c:crown-margin?Preserve the indentation of the first two lines within "
"a paragraph, and align the left margin of each subsequent line with "
"that of the second line.]"
"[o:optget?Format concatenated \boptget\b(3) usage strings.]"
"[s:split-only?Split lines only; do not join short lines to form longer "
"ones.]"
"[u:uniform-spacing?One space between words, two after sentences.]"
"[w:width?Set the output line width to \acolumns\a.]#[columns:=72]"
"\n\n"
"[ file ... ]"
"\n\n"
"[+SEE ALSO?\bmailx\b(1), \bnroff\b(1), \btroff\b(1), \bvi\b(1), "
"\boptget\b(3)]"
;
#include <cmd.h>
#include <ctype.h>
typedef struct Fmt_s
{
long flags;
char* outp;
char* outbuf;
char* endbuf;
int indent;
int nextdent;
int nwords;
int prefix;
int quote;
int retain;
int section;
} Fmt_t;
#define INDENT 4
#define TABSZ 8
static void
{
int n = 0;
int c;
int d;
return;
while (*cp++ == ' ')
n++;
if (n >= TABSZ)
{
n /= TABSZ;
while (n--)
*--cp = '\t';
}
else
else if (*cp)
{
if (*cp != '[')
{
if (*cp == ' ')
cp++;
n += INDENT;
}
while (n--)
{
c = 0;
c = '}';
}
else
{
}
}
}
static void
{
register char* cp;
register char* ep;
register char* qp;
register int c = 1;
register int q = 0;
register int n;
int prefix;
/*
* preserve blank lines
*/
{
if (*ep)
return;
}
while (c)
{
while (*ep == ' ')
ep++;
while (c = *ep)
{
if (c == ' ')
break;
ep++;
/*
* skip over \space
*/
if (c == '\\' && *ep)
ep++;
}
{
if (*qp == '\\')
qp++;
else if (*qp == '"')
q = !q;
goto skip;
}
skip:
{
while (*cp == ' ')
cp++;
}
}
{
/*
* two spaces at ends of sentences
*/
if (!splice && !fp->retain && (!fp->quote || (fp->outp - fp->outbuf) < 2 || fp->outp[-2] != '\\' || fp->outp[-1] != 'n' && fp->outp[-1] != 't' && fp->outp[-1] != ' '))
}
}
static int
{
register int c;
int b;
int x;
int splice;
char* cp;
char* dp;
char* ep;
char* lp;
char* tp;
char buf[8192];
cp = 0;
while (cp || (cp = sfgetr(fp->in, '\n', 0)) && !(splice = 0) && (lp = cp + sfvalue(fp->in) - 1) || (cp = sfgetr(fp->in, '\n', SF_LASTR)) && (splice = 1) && (lp = cp + sfvalue(fp->in)))
{
{
{
b = 0;
{
if (*cp == ' ')
b += 1;
else if (*cp == '\t')
b += INDENT;
else
break;
cp++;
}
}
else
cp++;
{
if (*cp == '"')
{
if (*ep == '"')
{
break;
}
break;
}
}
}
ep = 0;
for (b = 1;; b = 0)
{
{
cp = 0;
break;
}
c = *cp++;
{
if (c == '\\')
{
x = 0;
c = ' ';
cp--;
{
if (*cp == '\\')
{
cp++;
{
c = '\\';
break;
}
if (*cp == 'n')
{
cp++;
c = '\n';
{
{
*dp++ = '\\';
*dp++ = 'n';
c = *cp++;
break;
}
{
cp += 2;
*dp++ = '\n';
break;
}
}
}
{
cp++;
x = 1;
c = ' ';
}
else
{
*dp++ = ' ';
*dp++ = '\\';
c = *cp++;
break;
}
}
{
cp++;
c = ' ';
x = 1;
}
else
{
*dp++ = ' ';
break;
}
}
if (c == '\n')
{
c = 0;
goto flush;
}
continue;
}
else if (c == '"')
{
{
continue;
}
}
else if (c == '\a')
{
*dp++ = '\\';
c = 'a';
}
else if (c == '\b')
{
*dp++ = '\\';
c = 'b';
}
else if (c == '\f')
{
*dp++ = '\\';
c = 'f';
}
else if (c == '\v')
{
*dp++ = '\\';
c = 'v';
}
{
{
cp++;
*dp++ = c;
}
else
{
*dp++ = c;
*dp = 0;
goto again;
}
}
{
if (c == '[')
{
if (b)
else
{
cp--;
c = 0;
goto flush;
}
}
else if (c == '{')
{
x = 1;
{
break;
continue;
{
if (*++tp == 'n')
break;
continue;
}
x = 0;
break;
}
if (x)
{
goto flush;
}
else
}
else if (c == '}')
{
{
if (b)
{
}
else
{
cp--;
c = 0;
}
goto flush;
}
else
}
else if (c == ' ' || c == '\t')
continue;
else
}
{
{
cp--;
*dp = 0;
ep = 0;
continue;
}
}
else if (c == ' ' || c == '\t')
}
else if (c == '\b')
{
{
dp--;
if (ep)
ep--;
}
continue;
}
else if (c == '\t')
{
/*
* expand tabs
*/
if (!ep)
{
cp--;
break;
}
while (c-- > 0)
*dp++ = ' ';
continue;
}
else if (!isprint(c))
continue;
{
{
break;
}
ep = 0;
break;
}
if (c != ' ')
ep = 0;
else if (!ep)
*dp++ = c;
}
if (ep)
*ep = 0;
else
*dp = 0;
}
return 0;
}
int
{
register int n;
char* cp;
for (;;)
{
{
case 'c':
case 'o':
case 's':
case 'u':
continue;
case 'w':
continue;
case ':':
break;
case '?':
break;
}
break;
}
if (error_info.errors)
argv++;
do {
{
continue;
}
return error_info.errors != 0;
}