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:
parent
8141ce5d83
commit
a02c58f5a6
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue