Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sat,  6 Apr 2013 20:38:16 +0000
From: Nathan McSween <nwmcsween@...il.com>
To: musl@...ts.openwall.com
Cc: Nathan McSween <nwmcsween@...il.com>
Subject: [PATCH] String: expand to word size && refactor || refactor

---
 src/string/memccpy.c   | 50 ++++++++++++++++++++++++++----------------------
 src/string/memchr.c    | 42 +++++++++++++++++++++++-----------------
 src/string/memcmp.c    | 33 ++++++++++++++++++++++++++++----
 src/string/memcpy.c    | 44 +++++++++++++++++++++---------------------
 src/string/memrchr.c   | 30 +++++++++++++++++++++++++----
 src/string/memset.c    | 37 ++++++++++++++++++++---------------
 src/string/stpcpy.c    | 32 +++++++++++++++++--------------
 src/string/stpncpy.c   | 38 +++++++++++++++++++-----------------
 src/string/strcat.c    |  7 ++++---
 src/string/strchrnul.c | 26 ++++++++++++++-----------
 src/string/strcmp.c    | 30 ++++++++++++++++++++++++++++-
 src/string/strcpy.c    |  7 -------
 src/string/strlcpy.c   | 52 +++++++++++++++++++++++++++++---------------------
 13 files changed, 268 insertions(+), 160 deletions(-)

diff --git a/src/string/memccpy.c b/src/string/memccpy.c
index b85009c..f032030 100644
--- a/src/string/memccpy.c
+++ b/src/string/memccpy.c
@@ -1,32 +1,36 @@
 #include <string.h>
-#include <stdlib.h>
 #include <stdint.h>
-#include <limits.h>
 
-#define ALIGN (sizeof(size_t)-1)
-#define ONES ((size_t)-1/UCHAR_MAX)
-#define HIGHS (ONES * (UCHAR_MAX/2+1))
-#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+#define HIGHS(x) ((x) - ((x)*0-1) / 255 * 128)
+#define LOWS(x) (((x)*0-1) / 255)
+#define has_char(x, c) ((x) - LOWS(x) & ~(x) & HIGHS(x) ^ LOWS(x) * (c))
 
-void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
+void *memccpy(void *restrict d, const void *restrict s, int c, size_t n)
 {
-	unsigned char *d = dest;
-	const unsigned char *s = src;
-	size_t *wd, k;
+	unsigned char *cd = (unsigned char *)d;
+	const unsigned char *cs = (const unsigned char *)s;
+	size_t *wd;
 	const size_t *ws;
 
 	c = (unsigned char)c;
-	if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
-		for (; ((uintptr_t)s & ALIGN) && n && (*d=*s)!=c; n--, s++, d++);
-		if ((uintptr_t)s & ALIGN) goto tail;
-		k = ONES * c;
-		wd=(void *)d; ws=(const void *)s;
-		for (; n>=sizeof(size_t) && !HASZERO(*ws^k);
-		       n-=sizeof(size_t), ws++, wd++) *wd = *ws;
-		d=(void *)wd; s=(const void *)ws;
-	}
-	for (; n && (*d=*s)!=c; n--, s++, d++);
-tail:
-	if (*s==c) return d+1;
-	return 0;
+
+	if ((uintptr_t)s % sizeof(size_t) != (uintptr_t)d % sizeof(size_t)
+	    || n < sizeof(size_t))
+		goto bytewise;
+
+	for (; (uintptr_t)s % sizeof(size_t); *cd = *cs, cd++, cs++)
+		if (*cs == c) return cd + 1;
+
+	for (wd = (size_t *)d, ws = (const size_t *)s
+	     ; !has_char(*ws, c) && n >= sizeof(size_t)
+	     ; ws++, wd++, *wd = *ws);
+
+	cd = (unsigned char *)wd;
+	cs = (const unsigned char *)ws;
+
+bytewise:
+	for (; *cs != c; *cd = *cs, cs++, cd++, n--)
+		if (!n) return NULL;
+
+	return cd + 1;
 }
diff --git a/src/string/memchr.c b/src/string/memchr.c
index a0472f7..9a69a85 100644
--- a/src/string/memchr.c
+++ b/src/string/memchr.c
@@ -1,24 +1,32 @@
-#include <string.h>
-#include <stdlib.h>
+#include <stddef.h>
 #include <stdint.h>
-#include <limits.h>
+#include <string.h>
 
-#define SS (sizeof(size_t))
-#define ALIGN (sizeof(size_t)-1)
-#define ONES ((size_t)-1/UCHAR_MAX)
-#define HIGHS (ONES * (UCHAR_MAX/2+1))
-#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+#define HIGHS(x) ((x) - ((x)*0-1) / 255 * 128)
+#define LOWS(x) (((x)*0-1) / 255)
+#define has_char(x, c) ((x) - LOWS(x) & ~(x) & HIGHS(x) ^ LOWS(x) * (c))
 
-void *memchr(const void *src, int c, size_t n)
+void *memchr(const void *s, int c, size_t n)
 {
-	const unsigned char *s = src;
+	const unsigned char *cs = (const unsigned char *)s;
+	const size_t *ws;
+
 	c = (unsigned char)c;
-	for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
-	if (n && *s != c) {
-		const size_t *w;
-		size_t k = ONES * c;
-		for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
-		for (s = (const void *)w; n && *s != c; s++, n--);
+
+	if (n < sizeof(size_t)) goto bytewise;
+
+	for (; (uintptr_t)cs % sizeof(size_t); cs++, n--) {
+		if (*cs == c) return (void *)cs;
 	}
-	return n ? (void *)s : 0;
+
+	for (ws = (const size_t *)cs
+	     ; !has_char(*ws, c) && n >= sizeof(size_t)
+	     ; ws++, n -= sizeof(size_t));
+	cs = (const unsigned char *)ws;
+
+bytewise:
+	for (; *cs != c; cs++, n--)
+		if (!n) return NULL;
+
+	return (void *)cs;
 }
diff --git a/src/string/memcmp.c b/src/string/memcmp.c
index bdbce9f..81b1e80 100644
--- a/src/string/memcmp.c
+++ b/src/string/memcmp.c
@@ -1,8 +1,33 @@
+#include <stddef.h>
+#include <stdint.h>
 #include <string.h>
 
-int memcmp(const void *vl, const void *vr, size_t n)
+int memcmp(const void *s, const void *c, size_t n)
 {
-	const unsigned char *l=vl, *r=vr;
-	for (; n && *l == *r; n--, l++, r++);
-	return n ? *l-*r : 0;
+	const unsigned char *cs = (const unsigned char *)s;
+	const unsigned char *cc = (const unsigned char *)c;
+	const size_t *ws;
+	const size_t *wc;
+
+	if ((uintptr_t)cs % sizeof(size_t) != (uintptr_t)cc % sizeof(size_t)
+	    || n < sizeof(size_t)) {
+		goto bytewise;
+	}
+
+	for (; (uintptr_t)cs % sizeof(size_t); cs++, cc++, n--)
+		if (*cs == *cc) return *cs - *cc;
+
+	for (ws = (const size_t *)cs, wc = (const size_t *)cc
+	     ; *ws == *wc && n >= sizeof(size_t)
+	     ; ws++, wc++, n -= sizeof(size_t));
+	cs = (const unsigned char *)ws;
+	cc = (const unsigned char *)wc;
+
+bytewise:
+	for(; *cs == *cc; cs++, cc++, n--) {
+		if (!n) return 0;
+	}
+
+	return *cs - *cc;
 }
+
diff --git a/src/string/memcpy.c b/src/string/memcpy.c
index 8e98302..c34185c 100644
--- a/src/string/memcpy.c
+++ b/src/string/memcpy.c
@@ -1,29 +1,29 @@
-#include <string.h>
-#include <stdlib.h>
+#include <stddef.h>
 #include <stdint.h>
+#include <string.h>
 
-#define SS (sizeof(size_t))
-#define ALIGN (sizeof(size_t)-1)
-#define ONES ((size_t)-1/UCHAR_MAX)
-
-void *memcpy(void *restrict dest, const void *restrict src, size_t n)
+void *memcpy(void *restrict d, const void *restrict s, size_t n)
 {
-	unsigned char *d = dest;
-	const unsigned char *s = src;
+	unsigned char *cd = (unsigned char *)d;
+	const unsigned char *cs = (const unsigned char *)s;
+	size_t *wd;
+	const size_t *ws;
 
-	if (((uintptr_t)d & ALIGN) != ((uintptr_t)s & ALIGN))
-		goto misaligned;
+	if ((uintptr_t)cd % sizeof(size_t) != (uintptr_t)cs % sizeof(size_t)
+	    || n < sizeof(size_t)) {
+		goto bytewise;
+	}
 
-	for (; ((uintptr_t)d & ALIGN) && n; n--) *d++ = *s++;
-	if (n) {
-		size_t *wd = (void *)d;
-		const size_t *ws = (const void *)s;
+	for (; (uintptr_t)cd % sizeof(size_t); *cd++ = *cs++, n--);
 
-		for (; n>=SS; n-=SS) *wd++ = *ws++;
-		d = (void *)wd;
-		s = (const void *)ws;
-misaligned:
-		for (; n; n--) *d++ = *s++;
-	}
-	return dest;
+	for (wd = (size_t *)cd, ws = (const size_t *)cs
+	     ; n >= sizeof(size_t)
+	     ; n -= sizeof(size_t), *wd++ = *ws++);
+	cd = (unsigned char *)wd;
+	cs = (const unsigned char *)ws;
+
+bytewise:
+	for (; n; *cd++ = *cs++, n--);
+
+	return d;
 }
diff --git a/src/string/memrchr.c b/src/string/memrchr.c
index a78e9d6..e9bb838 100644
--- a/src/string/memrchr.c
+++ b/src/string/memrchr.c
@@ -1,12 +1,34 @@
+#include <stddef.h>
+#include <stdint.h>
 #include <string.h>
 #include "libc.h"
 
-void *__memrchr(const void *m, int c, size_t n)
+#define HIGHS(x) ((x) - ((x)*0-1) / 255 * 128)
+#define LOWS(x) (((x)*0-1) / 255)
+#define has_char(x, c) ((x) - LOWS(x) & ~(x) & HIGHS(x) ^ LOWS(x) * (c))
+
+void *__memrchr(const void *s, int c, size_t n)
 {
-	const unsigned char *s = m;
+	const unsigned char *cs = s;
+	const size_t *ws;
+
 	c = (unsigned char)c;
-	while (n--) if (s[n]==c) return (void *)(s+n);
-	return 0;
+
+	if (n < sizeof(size_t)) goto bytewise;
+
+	for (; (uintptr_t)s % sizeof(size_t); cs++, n--)
+		if (cs[n] == c) return (void *)(cs + n);
+
+	for (ws = (const size_t *)cs + n
+	     ; !has_char(*ws, c) && n >= sizeof(size_t)
+	     ; ws--, n -= sizeof(size_t));
+	cs = (const unsigned char *)ws;
+
+bytewise:
+	for (; n; n--)
+		if (cs[n] == c) return (void *)(cs + n);
+
+	return NULL;
 }
 
 weak_alias(__memrchr, memrchr);
diff --git a/src/string/memset.c b/src/string/memset.c
index 20e47c4..774829d 100644
--- a/src/string/memset.c
+++ b/src/string/memset.c
@@ -1,21 +1,28 @@
-#include <string.h>
-#include <stdlib.h>
+#include <stddef.h>
 #include <stdint.h>
-#include <limits.h>
+#include <string.h>
 
-#define SS (sizeof(size_t))
-#define ALIGN (sizeof(size_t)-1)
-#define ONES ((size_t)-1/UCHAR_MAX)
+#define LOWS(x) (((x)*0-1) / 255)
 
-void *memset(void *dest, int c, size_t n)
+void *memset(void *d, int c, size_t n)
 {
-	unsigned char *s = dest;
+	unsigned char *cd = (unsigned char *)d;
+	const size_t wc = LOWS(wc) * (unsigned char)c;
+	size_t *wd;
+
 	c = (unsigned char)c;
-	for (; ((uintptr_t)s & ALIGN) && n; n--) *s++ = c;
-	if (n) {
-		size_t *w, k = ONES * c;
-		for (w = (void *)s; n>=SS; n-=SS, w++) *w = k;
-		for (s = (void *)w; n; n--, s++) *s = c;
-	}
-	return dest;
+
+	if (n < sizeof(size_t)) goto bytewise;
+
+	for (; (uintptr_t)d % sizeof(size_t); *cd++ = c, n--);
+
+	for (wd = (size_t *)cd
+	     ; n >= sizeof(size_t)
+	     ; *wd++ = wc, n -= sizeof(size_t));
+	cd = (unsigned char *)wd;
+
+bytewise:
+	for (; n; *cd++ = c, n--);
+
+	return d;
 }
diff --git a/src/string/stpcpy.c b/src/string/stpcpy.c
index feb9eb8..6608c38 100644
--- a/src/string/stpcpy.c
+++ b/src/string/stpcpy.c
@@ -1,27 +1,31 @@
+#include <stddef.h>
 #include <string.h>
-#include <stdlib.h>
 #include <stdint.h>
-#include <limits.h>
 #include "libc.h"
 
-#define ALIGN (sizeof(size_t))
-#define ONES ((size_t)-1/UCHAR_MAX)
-#define HIGHS (ONES * (UCHAR_MAX/2+1))
-#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+#define HIGHS(x) ((x) - ((x)*0-1) / 255 * 128)
+#define LOWS(x) (((x)*0-1) / 255)
+#define has_zero(x) ((x) - LOWS(x) & ~(x) & HIGHS(x))
 
 char *__stpcpy(char *restrict d, const char *restrict s)
 {
 	size_t *wd;
 	const size_t *ws;
 
-	if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) {
-		for (; (uintptr_t)s % ALIGN; s++, d++)
-			if (!(*d=*s)) return d;
-		wd=(void *)d; ws=(const void *)s;
-		for (; !HASZERO(*ws); *wd++ = *ws++);
-		d=(void *)wd; s=(const void *)ws;
-	}
-	for (; (*d=*s); s++, d++);
+	if ((uintptr_t)s % sizeof(size_t) != (uintptr_t)d % sizeof(size_t))
+		goto bytewise;
+
+	for (; (uintptr_t)s % sizeof(size_t); s++, d++)
+		if (!(*d = *s)) return d;
+
+	for (wd = (size_t *)d, ws = (const size_t *)s
+	     ; !has_zero(*ws); wd++, ws++, *wd = *ws);
+
+	d = (char *)wd;
+	s = (const char *)ws;
+
+bytewise:
+	for (; (*d = *s); d++, s++);
 
 	return d;
 }
diff --git a/src/string/stpncpy.c b/src/string/stpncpy.c
index 0a2c2a9..c38d98d 100644
--- a/src/string/stpncpy.c
+++ b/src/string/stpncpy.c
@@ -1,32 +1,36 @@
+#include <stddef.h>
 #include <string.h>
-#include <stdlib.h>
 #include <stdint.h>
-#include <limits.h>
 #include "libc.h"
 
-#define ALIGN (sizeof(size_t)-1)
-#define ONES ((size_t)-1/UCHAR_MAX)
-#define HIGHS (ONES * (UCHAR_MAX/2+1))
-#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+#define HIGHS(x) ((x) - ((x)*0-1) / 255 * 128)
+#define LOWS(x) (((x)*0-1) / 255)
+#define has_zero(x) ((x) - LOWS(x) & ~(x) & HIGHS(x))
 
 char *__stpncpy(char *restrict d, const char *restrict s, size_t n)
 {
 	size_t *wd;
 	const size_t *ws;
 
-	if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
-		for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
-		if (!n || !*s) goto tail;
-		wd=(void *)d; ws=(const void *)s;
-		for (; n>=sizeof(size_t) && !HASZERO(*ws);
-		       n-=sizeof(size_t), ws++, wd++) *wd = *ws;
-		d=(void *)wd; s=(const void *)ws;
-	}
-	for (; n && (*d=*s); n--, s++, d++);
-tail:
+	if ((uintptr_t)s % sizeof(size_t) == (uintptr_t)d % sizeof(size_t))
+		goto bytewise;
+
+	for (; (uintptr_t)s % sizeof(size_t) && (*d = *s); d++, s++, n--)
+		if (!n || !*s) goto terminate;
+
+	for (wd = (size_t *)d, ws = (const size_t *)s
+	     ; !has_zero(*ws) && n >= sizeof(size_t)
+	     ; n -= sizeof(size_t), ws++, wd++, *wd = *ws);
+
+	d = (char *)wd;
+	s = (const char *)ws;
+
+bytewise:
+	for (; (*d = *s) && n; d++, s++, n--);
+terminate:
 	memset(d, 0, n);
+
 	return d;
 }
 
 weak_alias(__stpncpy, stpncpy);
-
diff --git a/src/string/strcat.c b/src/string/strcat.c
index 33f749b..0919793 100644
--- a/src/string/strcat.c
+++ b/src/string/strcat.c
@@ -1,7 +1,8 @@
 #include <string.h>
 
-char *strcat(char *restrict dest, const char *restrict src)
+char *strcat(char *restrict d, const char *restrict s)
 {
-	strcpy(dest + strlen(dest), src);
-	return dest;
+	strcpy(d + strlen(d), s);
+
+	return d;
 }
diff --git a/src/string/strchrnul.c b/src/string/strchrnul.c
index ceae4d4..cebd063 100644
--- a/src/string/strchrnul.c
+++ b/src/string/strchrnul.c
@@ -1,26 +1,30 @@
+#include <stddef.h>
 #include <string.h>
-#include <stdlib.h>
 #include <stdint.h>
-#include <limits.h>
 #include "libc.h"
 
-#define ALIGN (sizeof(size_t))
-#define ONES ((size_t)-1/UCHAR_MAX)
-#define HIGHS (ONES * (UCHAR_MAX/2+1))
-#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+#define HIGHS(x) ((x) - ((x)*0-1) / 255 * 128)
+#define LOWS(x) (((x)*0-1) / 255)
+#define has_zero(x) ((x) - LOWS(x) & ~(x) & HIGHS(x))
+#define has_char(x, c) ((x) - LOWS(x) & ~(x) & HIGHS(x) ^ LOWS(x) * (c))
 
 char *__strchrnul(const char *s, int c)
 {
-	size_t *w, k;
+	const size_t *ws;
 
 	c = (unsigned char)c;
+
 	if (!c) return (char *)s + strlen(s);
 
-	for (; (uintptr_t)s % ALIGN; s++)
+	for (; (uintptr_t)s % sizeof(size_t); s++)
 		if (!*s || *(unsigned char *)s == c) return (char *)s;
-	k = ONES * c;
-	for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
-	for (s = (void *)w; *s && *(unsigned char *)s != c; s++);
+
+	for (ws = (const size_t *)s; !has_zero(*ws) && !has_char(*ws, c); ws++);
+
+	s = (const char *)ws;
+
+	for (; *s && *(unsigned char *)s != c; s++);
+
 	return (char *)s;
 }
 
diff --git a/src/string/strcmp.c b/src/string/strcmp.c
index 91eb740..98b5e58 100644
--- a/src/string/strcmp.c
+++ b/src/string/strcmp.c
@@ -1,7 +1,35 @@
+#include <stddef.h>
+#include <stdint.h>
 #include <string.h>
 
+#define HIGHS(x) ((x) - ((x)*0-1) / 255 * 128)
+#define LOWS(x) (((x)*0-1) / 255)
+#define has_zero(x) ((x) - LOWS(x) & ~(x) & HIGHS(x))
+
+#undef strcmp
 int strcmp(const char *l, const char *r)
 {
-	for (; *l==*r && *l && *r; l++, r++);
+	const size_t *wl;
+	const size_t *wr;
+
+	if ((uintptr_t)l % sizeof(size_t) != (uintptr_t)r % sizeof(size_t))
+		goto bytewise;
+
+	for (; (uintptr_t)l % sizeof(size_t); l++, r++) {
+		if (*l != *r || !*l || !*r) {
+			return *(unsigned char *)l
+			       - *(unsigned char *)r;
+		}
+	}
+
+	for (wl = (const size_t *)l, wr = (const size_t *)r
+	     ; has_zero(*wl) || has_zero(*wr) && *wl == *wr
+	     ; wl++, wr++);
+	l = (const char *)wl;
+	r = (const char *)wr;
+
+bytewise:
+	for(; *l == *r && *l && *r; l++, r++);
+
 	return *(unsigned char *)l - *(unsigned char *)r;
 }
diff --git a/src/string/strcpy.c b/src/string/strcpy.c
index f7e3ba3..2883e93 100644
--- a/src/string/strcpy.c
+++ b/src/string/strcpy.c
@@ -4,13 +4,6 @@ char *__stpcpy(char *, const char *);
 
 char *strcpy(char *restrict dest, const char *restrict src)
 {
-#if 1
 	__stpcpy(dest, src);
 	return dest;
-#else
-	const unsigned char *s = src;
-	unsigned char *d = dest;
-	while ((*d++ = *s++));
-	return dest;
-#endif
 }
diff --git a/src/string/strlcpy.c b/src/string/strlcpy.c
index 4d3ff92..42b63e1 100644
--- a/src/string/strlcpy.c
+++ b/src/string/strlcpy.c
@@ -1,32 +1,40 @@
-#include <string.h>
-#include <stdlib.h>
+#include <stddef.h>
 #include <stdint.h>
-#include <limits.h>
-#include "libc.h"
+#include <string.h>
 
-#define ALIGN (sizeof(size_t)-1)
-#define ONES ((size_t)-1/UCHAR_MAX)
-#define HIGHS (ONES * (UCHAR_MAX/2+1))
-#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+#define HIGHS(x) ((x) - ((x)*0-1) / 255 * 128)
+#define LOWS(x) (((x)*0-1) / 255)
+#define has_zero(x) ((x) - LOWS(x) & ~(x) & HIGHS(x))
 
 size_t strlcpy(char *d, const char *s, size_t n)
 {
-	char *d0 = d;
+	char *ds = d;
 	size_t *wd;
 	const size_t *ws;
 
-	if (!n--) goto finish;
-	if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
-		for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
-		if (n && *s) {
-			wd=(void *)d; ws=(const void *)s;
-			for (; n>=sizeof(size_t) && !HASZERO(*ws);
-			       n-=sizeof(size_t), ws++, wd++) *wd = *ws;
-			d=(void *)wd; s=(const void *)ws;
-		}
+	if (!n--) goto ret;
+
+	if ((uintptr_t)d % sizeof(size_t) != (uintptr_t)s % sizeof(size_t)
+	    || n < sizeof(size_t)) {
+		goto bytewise;
 	}
-	for (; n && (*d=*s); n--, s++, d++);
-	*d = 0;
-finish:
-	return d-d0 + strlen(s);
+
+	for (; (uintptr_t)s % sizeof(size_t); *d++ = *s++, n--)
+		if (!*s) goto terminate;
+
+	for (wd = (size_t *)d, ws = (const size_t *)s
+	     ; !has_zero(*ws) && n >= sizeof(size_t)
+	     ; *wd++ = *ws++, n -= sizeof(size_t))
+
+	d = (char *)wd;
+	s = (const char *)ws;
+
+bytewise:
+	for (; (*d = *s) && n; d++, s++, n--);
+
+terminate:
+	*d = '\0';
+
+ret:
+	return (d - ds + strlen(s));
 }
-- 
1.8.1.2

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.