Index | Thread | Search

From:
"Andy Bradford" <amb-sendok-1715569415.nmicbecdkkdmdcombafb@bradfords.org>
Subject:
Implement -E for rs(1)
To:
tech@openbsd.org
Date:
13 Mar 2024 21:03:34 -0600

Download raw body.

Thread
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 <wchar.h>
 
 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]