#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <euc.h>
#include <stdlib.h>
#include <limits.h>
#include <libintl.h>
#include <langinfo.h>
#include <utime.h>
#include <widec.h>
#include <wctype.h>
#include <errno.h>
static int fold = 80;
static int bflg = 0;
static int sflg = 0;
static int wflg = 0;
static int lastc = 0;
static int col = 0;
static int ncol = 0;
static int spcol = 0;
static wchar_t line[LINE_MAX];
static wchar_t *lastout = line;
static wchar_t *curc = line;
static wchar_t *lastsp = NULL;
#define MAXARG _POSIX_ARG_MAX
void exit();
static void Usage();
static void putch();
static void newline_init();
static int chr_width();
extern int errno;
static int get_foldw();
int
main(int argc, char *argv[])
{
int c, narg;
int ch;
char *cmdline[MAXARG];
int new_argc;
int w;
extern int optind;
extern char *optarg;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
for (narg = new_argc = 0; narg < argc; narg ++) {
if (argv[narg][0] == '-' &&
isdigit(argv[narg][1])) {
if (get_foldw((char *)&argv[narg][1], &w) < 0)
exit(1);
fold = w;
} else {
cmdline[new_argc++] = argv[narg];
if ((argv[narg][0] == '-') && (argv[narg][1] == 'w')) {
if (((narg+1) < argc) &&
(argv[narg+1][0] == '-')) {
(void) fprintf(stderr, "fold");
(void) fprintf(stderr, gettext(
": option requires an argument -- w\n"));
Usage();
exit(1);
}
}
}
}
while ((ch = getopt(new_argc, cmdline, "w:bs")) != EOF) {
switch (ch) {
case 'b':
bflg++;
break;
case 's':
sflg++;
break;
case 'w':
wflg++;
if ((optarg == (char *)NULL) ||
((optarg != (char *)NULL) &&
(*optarg == '-'))) {
(void) fprintf(stderr, "fold");
(void) fprintf(stderr, gettext(
": option requires an argument -- w\n"));
Usage();
exit(1);
}
if (get_foldw(optarg, &w) < 0)
exit(1);
fold = w;
break;
default:
Usage();
exit(1);
}
}
do {
if (new_argc > optind) {
if (freopen(cmdline[optind], "r", stdin) == NULL) {
perror(cmdline[optind]);
Usage();
exit(1);
}
optind++;
}
for (;;) {
c = getwc(stdin);
if (c == EOF)
break;
(void) putch(c);
lastc = c;
}
if (col != 0) newline_init();
} while (new_argc > optind);
return (0);
}
static void
putch(int c)
{
wchar_t tline[LINE_MAX];
switch (c) {
case '\n':
ncol = 0;
break;
case '\t':
if (bflg)
ncol = col + chr_width(c);
else
ncol = (col + 8) &~ 7;
break;
case '\b':
if (bflg)
ncol = col + chr_width(c);
else
ncol = col ? col - 1 : 0;
break;
case '\r':
if (bflg)
ncol = col + chr_width(c);
else
ncol = 0;
break;
default:
if (bflg)
ncol = col + chr_width(c);
else
ncol = col + wcwidth(c);
}
if ((ncol > fold) && (bflg ||
(!bflg && (lastc != '\b') && (c != '\b') &&
(lastc != '\n') && (c != '\n')))) {
if (sflg && lastsp) {
(void) wscpy(tline, line);
*lastsp = (wchar_t)NULL;
(void) fputws(lastout, stdout);
(void) putwchar('\n');
(void) wscpy(line, tline);
lastout = lastsp;
lastsp = NULL;
ncol -= spcol;
col -= spcol;
} else {
(void) newline_init();
(void) putwchar('\n');
lastout = curc;
}
}
if ((curc + 1) >= (line + LINE_MAX)) {
if (col > 0) {
*curc = (wchar_t)NULL;
(void) fputws(lastout, stdout);
lastsp = NULL;
}
curc = lastout = line;
}
*curc++ = (wchar_t)c;
switch (c) {
case '\n':
(void) newline_init();
curc = lastout = line;
break;
case '\t':
if (bflg)
col = col + chr_width(c);
else
col = (col + 8) &~ 7;
if (sflg && iswspace(c)) {
lastsp = curc;
spcol = ncol;
}
break;
case '\b':
if (bflg)
col = ncol;
else {
if (col)
col--;
}
break;
case '\r':
col = 0;
break;
default:
if (sflg && iswspace(c)) {
lastsp = curc;
spcol = ncol;
}
if (bflg)
col += chr_width(c);
else
col += wcwidth(c);
break;
}
}
static
void
Usage()
{
(void) fprintf(stderr, gettext(
"Usage: fold [-bs] [-w width | -width ] [file...]\n"));
}
static
void
newline_init()
{
*curc = (wchar_t)NULL;
(void) fputws(lastout, stdout);
ncol = col = spcol = 0;
lastsp = NULL;
}
static int
chr_width(c)
register int c;
{
char chr[MB_LEN_MAX+1];
register int n;
n = wctomb(chr, (wchar_t)c);
return (n > 0 ? n : 0);
}
static int
get_foldw(toptarg, width)
char *toptarg;
int *width;
{
char *p;
if (!toptarg)
goto badno;
*width = 0;
errno = 0;
*width = strtoul(toptarg, &p, 10);
if (*width == -1)
goto badno;
if (*p)
goto badno;
if (!*width)
goto badno;
return (0);
badno:
(void) fprintf(stderr, gettext(
"Bad number for fold\n"));
Usage();
return (-1);
}