Make POSIX 1003.2 (D11.2) compliant by adding -s (split at blank) and

-b (count bytes, not column positions) flags.
This commit is contained in:
jtc 1993-07-19 23:22:09 +00:00
parent 8141ce5d83
commit a02c58f5a6
2 changed files with 112 additions and 34 deletions

View File

@ -49,16 +49,25 @@ breaking the lines to have maximum of 80 characters.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl b
Count
.Ar width
in bytes rather than column positions.
.It Fl s
Fold line after the last blank character within the first
.Ar width
column positions (or bytes).
.It Fl w
Specifies a line width to use instead of the default 80 characters.
.El
.Sh SEE ALSO
.Xr expand 1
.Sh BUGS
If underlining is present it may be messed up by folding.
.Pp
.Ar Width
should be a multiple of 8 if tabs are present, or the tabs should
be expanded using
.Xr expand 1
before using
.Nm fold .
.El
.Sh SEE ALSO
.Xr expand 1
.Sh BUGS
If underlining is present it may be messed up by folding.

View File

@ -45,23 +45,35 @@ static char sccsid[] = "@(#)fold.c 5.5 (Berkeley) 6/1/90";
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define DEFLINEWIDTH 80
static void fold ();
static int new_column_position ();
int count_bytes = 0;
int split_words = 0;
int
main(argc, argv)
int argc;
char **argv;
{
extern int errno, optind;
extern char *optarg;
register int ch;
int width;
char *p;
width = -1;
while ((ch = getopt(argc, argv, "0123456789w:")) != EOF)
while ((ch = getopt(argc, argv, "0123456789bsw:")) != EOF)
switch (ch) {
case 'b':
count_bytes = 1;
break;
case 's':
split_words = 1;
break;
case 'w':
if ((width = atoi(optarg)) <= 0) {
(void)fprintf(stderr,
@ -89,6 +101,7 @@ main(argc, argv)
if (width == -1)
width = DEFLINEWIDTH;
if (!*argv)
fold(width);
else for (; *argv; ++argv)
@ -101,52 +114,108 @@ main(argc, argv)
exit(0);
}
/*
* Fold the contents of standard input to fit within WIDTH columns
* (or bytes) and write to standard output.
*
* If split_words is set, split the line at the last space character
* on the line. This flag necessitates storing the line in a buffer
* until the current column > width, or a newline or EOF is read.
*
* The buffer can grow larger than WIDTH due to backspaces and carriage
* returns embedded in the input stream.
*/
static void
fold(width)
register int width;
{
register int ch, col, new;
static char *buf = NULL;
static int buf_max = 0;
register int ch, col;
register int indx;
for (col = 0;;) {
switch (ch = getchar()) {
case EOF:
return;
case '\b':
new = col ? col - 1 : 0;
break;
case '\n':
case '\r':
new = 0;
break;
case '\t':
new = (col + 8) & ~7;
break;
default:
new = col + 1;
break;
}
if (new > width) {
col = indx = 0;
while ((ch = getchar()) != EOF) {
if (ch == '\n') {
if (indx != 0)
fwrite (buf, 1, indx, stdout);
putchar('\n');
col = 0;
col = indx = 0;
continue;
}
putchar(ch);
col = new_column_position (col, ch);
if (col > width) {
int i, last_space;
if (split_words) {
for (i = 0, last_space = -1; i < indx; i++)
if(buf[i] == ' ') last_space = i;
}
if (split_words && last_space != -1) {
last_space++;
fwrite (buf, 1, last_space, stdout);
memmove (buf, buf+last_space, indx-last_space);
indx -= last_space;
col = 0;
for (i = 0; i < indx; i++) {
col = new_column_position (col, ch);
}
} else {
fwrite (buf, 1, indx, stdout);
col = indx = 0;
}
putchar('\n');
/* calculate the column position for the next line. */
col = new_column_position (col, ch);
}
if (indx + 1 > buf_max) {
/* Allocate buffer in LINE_MAX increments */
buf_max += 2048;
if((buf = realloc (buf, buf_max)) == NULL) {
(void)fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
}
buf[indx++] = ch;
}
if (indx != 0)
fwrite (buf, 1, indx, stdout);
}
/*
* calculate the column position
*/
static int
new_column_position (col, ch)
int col;
int ch;
{
if (!count_bytes) {
switch (ch) {
case '\b':
if (col > 0)
--col;
break;
case '\n':
case '\r':
col = 0;
break;
case '\t':
col += 8;
col &= ~7;
col = (col + 8) & ~7;
break;
default:
++col;
break;
}
} else {
++col;
}
return col;
}