summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortjr <tjr@FreeBSD.org>2004-07-13 04:35:43 +0000
committertjr <tjr@FreeBSD.org>2004-07-13 04:35:43 +0000
commit8c666334680aacd31f60791f869b43362cc3e41e (patch)
treef87f7b40bb0cef82e81bb68ea1fdaef5e52411e5
parentea94acfaa697b466403b3bf0b16d4772ff5ab621 (diff)
downloadFreeBSD-src-8c666334680aacd31f60791f869b43362cc3e41e.zip
FreeBSD-src-8c666334680aacd31f60791f869b43362cc3e41e.tar.gz
Overhaul lputs() to deal with multibyte characters, characters that take
up more than one column position, and null bytes.
-rw-r--r--usr.bin/sed/process.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/usr.bin/sed/process.c b/usr.bin/sed/process.c
index 772fd0b..0d63994 100644
--- a/usr.bin/sed/process.c
+++ b/usr.bin/sed/process.c
@@ -57,6 +57,8 @@ static const char sccsid[] = "@(#)process.c 8.6 (Berkeley) 4/20/94";
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
#include "defs.h"
#include "extern.h"
@@ -70,7 +72,7 @@ static SPACE HS, PS, SS;
static __inline int applies(struct s_command *);
static void flush_appends(void);
-static void lputs(char *);
+static void lputs(char *, size_t);
static __inline int regexec_e(regex_t *, const char *, int, int, size_t);
static void regsub(SPACE *, char *, char *);
static int substitute(struct s_command *);
@@ -165,7 +167,7 @@ redirect:
(void)fprintf(outfile, "%s", cp->t);
break;
case 'l':
- lputs(ps);
+ lputs(ps, psl);
break;
case 'n':
if (!nflag && !pd)
@@ -462,13 +464,16 @@ flush_appends(void)
}
static void
-lputs(char *s)
+lputs(char *s, size_t len)
{
- int count;
- const char *escapes;
+ static const char escapes[] = "\\\a\b\f\r\t\v";
+ int c, col, width;
char *p;
struct winsize win;
static int termwidth = -1;
+ size_t clen, i;
+ wchar_t wc;
+ mbstate_t mbs;
if (outfile != stdout)
termwidth = 60;
@@ -482,30 +487,54 @@ lputs(char *s)
termwidth = 60;
}
- for (count = 0; *s; ++s) {
- if (count + 5 >= termwidth) {
- (void)fprintf(outfile, "\\\n");
- count = 0;
+ memset(&mbs, 0, sizeof(mbs));
+ col = 0;
+ while (len != 0) {
+ clen = mbrtowc(&wc, s, len, &mbs);
+ if (clen == 0)
+ clen = 1;
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ wc = (unsigned char)*s;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
}
- if (isprint((unsigned char)*s) && *s != '\\') {
- (void)fputc(*s, outfile);
- count++;
- } else if (*s == '\n') {
- (void)fputc('$', outfile);
- (void)fputc('\n', outfile);
- count = 0;
+ if (wc == '\n') {
+ if (col + 1 >= termwidth)
+ fprintf(outfile, "\\\n");
+ fputc('$', outfile);
+ fputc('\n', outfile);
+ col = 0;
+ } else if (iswprint(wc)) {
+ width = wcwidth(wc);
+ if (col + width >= termwidth) {
+ fprintf(outfile, "\\\n");
+ col = 0;
+ }
+ fwrite(s, 1, clen, outfile);
+ col += width;
+ } else if (wc != L'\0' && (c = wctob(wc)) != EOF &&
+ (p = strchr(escapes, c)) != NULL) {
+ if (col + 2 >= termwidth) {
+ fprintf(outfile, "\\\n");
+ col = 0;
+ }
+ fprintf(outfile, "\\%c", "\\abfrtv"[p - escapes]);
+ col += 2;
} else {
- escapes = "\\\a\b\f\r\t\v";
- (void)fputc('\\', outfile);
- if ((p = strchr(escapes, *s))) {
- (void)fputc("\\abfrtv"[p - escapes], outfile);
- count += 2;
- } else {
- (void)fprintf(outfile, "%03o", *(u_char *)s);
- count += 4;
+ if (col + 4 * clen >= termwidth) {
+ fprintf(outfile, "\\\n");
+ col = 0;
}
+ for (i = 0; i < clen; i++)
+ fprintf(outfile, "\\%03o",
+ (int)(unsigned char)s[i]);
+ col += 4 * clen;
}
+ s += clen;
+ len -= clen;
}
+ if (col + 1 >= termwidth)
+ fprintf(outfile, "\\\n");
(void)fputc('$', outfile);
(void)fputc('\n', outfile);
if (ferror(outfile))
OpenPOWER on IntegriCloud