From: "Andy Bradford" Subject: Implement -E for rs(1) To: tech@openbsd.org Date: 13 Mar 2024 21:03:34 -0600 Hello, It looks like -E was never added to rs(1) for some reason even though the man page and the code make reference to it. I recently had need to have rs -E work, so I took a stab at implementing it. Here is what it does: $ echo ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz | ./rs -E 4 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z Comments on the patch? Should the code also handle allocating less memory when only a single char is necessary requested (I did start on that but it was less simple)? Index: rs.c =================================================================== RCS file: /cvs/src/usr.bin/rs/rs.c,v retrieving revision 1.30 diff -u -r1.30 rs.c --- rs.c 3 Dec 2015 12:23:15 -0000 1.30 +++ rs.c 23 Nov 2023 00:39:30 -0000 @@ -81,7 +81,7 @@ char isep = ' ', osep = ' '; int owidth = 80, gutter = 2; -int mbsavis(char **, const char *); +int mbsavis(char **, const char *, int); void usage(void); void getargs(int, char *[]); @@ -120,10 +120,11 @@ getfile(void) { const char delim[2] = { isep, '\0' }; - char *p; + char *p, *f; struct entry *ep; int multisep = (flags & ONEISEPONLY ? 0 : 1); int nullpad = flags & NULLPAD; + int oneperchar = flags & ONEPERCHAR; struct entry *padto; curline = NULL; @@ -139,6 +140,8 @@ flags |= ONEPERLINE; if (flags & ONEPERLINE) icols = 1; + else if (oneperchar) + icols = mbsavis(&f, curline, 0); else /* count cols on first line */ for (p = curline; *p != '\0'; p++) { if (*p == isep && multisep) @@ -151,7 +154,7 @@ p = curline; do { if (flags & ONEPERLINE) { - ep->w = mbsavis(&ep->s, curline); + ep->w = mbsavis(&ep->s, curline, 0); if (maxwidth < ep->w) maxwidth = ep->w; INCR(ep); /* prepare for next entry */ @@ -160,14 +163,17 @@ } p = curline; while (p != NULL && *p != '\0') { - if (*p == isep) { + if (oneperchar) { + ep->w = mbsavis(&ep->s, p, 1); + p += ep->w; + } else if (*p == isep) { p++; if (multisep) continue; ep->s = ""; /* empty column */ ep->w = 0; } else - ep->w = mbsavis(&ep->s, strsep(&p, delim)); + ep->w = mbsavis(&ep->s, strsep(&p, delim), 0); if (maxwidth < ep->w) maxwidth = ep->w; INCR(ep); /* prepare for next entry */ Index: utf8.c =================================================================== RCS file: /cvs/src/usr.bin/rs/utf8.c,v retrieving revision 1.1 diff -u -r1.1 utf8.c --- utf8.c 3 Dec 2015 12:23:15 -0000 1.1 +++ utf8.c 23 Nov 2023 00:39:30 -0000 @@ -20,7 +20,7 @@ #include int -mbsavis(char** outp, const char *mbs) +mbsavis(char** outp, const char *mbs, int nchars) { const char *src; /* Iterate mbs. */ char *dst; /* Iterate *outp. */ @@ -28,13 +28,16 @@ int total_width; /* Display width of the whole string. */ int width; /* Display width of a single Unicode char. */ int len; /* Length in bytes of UTF-8 encoded string. */ + int count; /* Count of chars read. */ len = strlen(mbs); if ((*outp = malloc(len + 1)) == NULL) err(1, NULL); if (MB_CUR_MAX == 1) { + len = (nchars && nchars < len) ? nchars : len; memcpy(*outp, mbs, len + 1); + (*outp)[len] = '\0'; return len; } @@ -55,6 +58,7 @@ while (len-- > 0) *dst++ = *src++; } + if (nchars > 0 && count++ >= nchars) break; } *dst = '\0'; return total_width; ------------------------------------------------------------------------ Thanks, Andy [resent]