about summary refs log tree commit diff
path: root/posix
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-11-10 15:48:06 +0000
committerUlrich Drepper <drepper@redhat.com>2004-11-10 15:48:06 +0000
commitbb677c9581b95720df6b28c375a3278d69e06f44 (patch)
treedc9745fd89d8cb3afbab86c2c901bce1ce2b5091 /posix
parented2ced8ae324a8a89a76ff3fc3971226b0107d3e (diff)
downloadglibc-bb677c9581b95720df6b28c375a3278d69e06f44.tar.gz
glibc-bb677c9581b95720df6b28c375a3278d69e06f44.tar.xz
glibc-bb677c9581b95720df6b28c375a3278d69e06f44.zip
Update.
2004-11-09  Paolo Bonzini  <bonzini@gnu.org>

	* posix/regexec.c (transit_state): Remove the check for
	out-of-bounds buffers.
	(check_matching): Check here for out-of-bounds buffers.
	(re_search_internal): Store into match_kind a set of bits
	indicating which incantation of fastmap scanning must be
	used.  Use a switch statement instead of multiple ifs.
	Exit the final "for (;;)" with goto free_return unless
	the match succeeded, thus simplifying some conditionals.

	* posix/regex_internal.c (re_string_reconstruct,
	re_string_context_at): Add several branch predictions for
	case-sensitive matching and no transition table being used.

2004-11-10  Ulrich Drepper  <drepper@redhat.com>

	* posix/tst-waitid.c: Don't use error to print error message, they
	won't end up in the .out file.

	* nscd/nscd_getgr_r.c: Likewise.  Make map externally visible.
	* nscd/nscd_gethst_r.c: Likewise.
Diffstat (limited to 'posix')
-rw-r--r--posix/regex_internal.c34
-rw-r--r--posix/regexec.c288
-rw-r--r--posix/tst-waitid.c171
3 files changed, 250 insertions, 243 deletions
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index 609719f79c..bb1d73d9a0 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -576,7 +576,7 @@ re_string_reconstruct (pstr, idx, eflags)
      int idx, eflags;
 {
   int offset = idx - pstr->raw_mbs_idx;
-  if (offset < 0)
+  if (BE (offset < 0, 0))
     {
       /* Reset buffer.  */
 #ifdef RE_ENABLE_I18N
@@ -596,10 +596,10 @@ re_string_reconstruct (pstr, idx, eflags)
       offset = idx;
     }
 
-  if (offset != 0)
+  if (BE (offset != 0, 1))
     {
       /* Are the characters which are already checked remain?  */
-      if (offset < pstr->valid_raw_len
+      if (BE (offset < pstr->valid_raw_len, 1)
 #ifdef RE_ENABLE_I18N
 	  /* Handling this would enlarge the code too much.
 	     Accept a slowdown in that case.  */
@@ -614,7 +614,7 @@ re_string_reconstruct (pstr, idx, eflags)
 	    memmove (pstr->wcs, pstr->wcs + offset,
 		     (pstr->valid_len - offset) * sizeof (wint_t));
 #endif /* RE_ENABLE_I18N */
-	  if (pstr->mbs_allocated)
+	  if (BE (pstr->mbs_allocated, 0))
 	    memmove (pstr->mbs, pstr->mbs + offset,
 		     pstr->valid_len - offset);
 	  pstr->valid_len -= offset;
@@ -711,7 +711,7 @@ re_string_reconstruct (pstr, idx, eflags)
 				      ? CONTEXT_NEWLINE : 0));
 	    }
 	}
-      if (!pstr->mbs_allocated)
+      if (!BE (pstr->mbs_allocated, 0))
 	pstr->mbs += offset;
     }
   pstr->raw_mbs_idx = idx;
@@ -733,16 +733,17 @@ re_string_reconstruct (pstr, idx, eflags)
     }
   else
 #endif /* RE_ENABLE_I18N */
+  if (BE (pstr->mbs_allocated, 0))
     {
       if (pstr->icase)
 	build_upper_buffer (pstr);
       else if (pstr->trans != NULL)
 	re_string_translate_buffer (pstr);
-      else
-	pstr->valid_len = pstr->len;
     }
-  pstr->cur_idx = 0;
+  else
+    pstr->valid_len = pstr->len;
 
+  pstr->cur_idx = 0;
   return REG_NOERROR;
 }
 
@@ -840,16 +841,13 @@ re_string_context_at (input, idx, eflags)
      int idx, eflags;
 {
   int c;
-  if (idx < 0 || idx == input->len)
-    {
-      if (idx < 0)
-	/* In this case, we use the value stored in input->tip_context,
-	   since we can't know the character in input->mbs[-1] here.  */
-	return input->tip_context;
-      else /* (idx == input->len) */
-	return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
-		: CONTEXT_NEWLINE | CONTEXT_ENDBUF);
-    }
+  if (BE (idx < 0, 0))
+    /* In this case, we use the value stored in input->tip_context,
+       since we can't know the character in input->mbs[-1] here.  */
+    return input->tip_context;
+  if (BE (idx == input->len, 0))
+    return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
+	    : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
 #ifdef RE_ENABLE_I18N
   if (input->mb_cur_max > 1)
     {
diff --git a/posix/regexec.c b/posix/regexec.c
index 72ae70b916..e6d92577a7 100644
--- a/posix/regexec.c
+++ b/posix/regexec.c
@@ -606,15 +606,16 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
   reg_errcode_t err;
   re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
   int left_lim, right_lim, incr;
-  int fl_longest_match, match_first, match_last = -1;
-  int fast_translate, sb;
+  int fl_longest_match, match_first, match_kind, match_last = -1;
+  int sb, ch;
 #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
   re_match_context_t mctx = { .dfa = dfa };
 #else
   re_match_context_t mctx;
 #endif
-  char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate
-		    && range && !preg->can_be_null) ? preg->fastmap : NULL);
+  char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate
+		   && range && !preg->can_be_null) ? preg->fastmap : NULL;
+  unsigned RE_TRANSLATE_TYPE t = (unsigned RE_TRANSLATE_TYPE) preg->translate;
 
 #if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
   memset (&mctx, '\0', sizeof (re_match_context_t));
@@ -685,88 +686,100 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
   left_lim = (range < 0) ? start + range : start;
   right_lim = (range < 0) ? start : start + range;
   sb = dfa->mb_cur_max == 1;
-  fast_translate = sb || !(preg->syntax & RE_ICASE || preg->translate);
-
-  for (;;)
+  match_kind =
+    (fastmap
+     ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
+	| (range >= 0 ? 2 : 0)
+	| (t != NULL ? 1 : 0))
+     : 8);
+
+  for (;; match_first += incr)
     {
-      /* At first get the current byte from input string.  */
-      if (fastmap)
+      err = REG_NOMATCH;
+      if (match_first < left_lim || right_lim < match_first)
+	goto free_return;
+
+      /* Advance as rapidly as possible through the string, until we
+	 find a plausible place to start matching.  This may be done
+	 with varying efficiency, so there are various possibilities:
+	 only the most common of them are specialized, in order to
+	 save on code size.  We use a switch statement for speed.  */
+      switch (match_kind)
 	{
-	  if (BE (fast_translate, 1))
+	case 8:
+	  /* No fastmap.  */
+	  break;
+
+	case 7:
+	  /* Fastmap with single-byte translation, match forward.  */
+	  while (BE (match_first < right_lim, 1)
+		 && !fastmap[t[(unsigned char) string[match_first]]])
+	    ++match_first;
+	  goto forward_match_found_start_or_reached_end;
+
+	case 6:
+	  /* Fastmap without translation, match forward.  */
+	  while (BE (match_first < right_lim, 1)
+		 && !fastmap[(unsigned char) string[match_first]])
+	    ++match_first;
+
+	forward_match_found_start_or_reached_end:
+	  if (BE (match_first == right_lim, 0))
 	    {
-	      unsigned RE_TRANSLATE_TYPE t
-		= (unsigned RE_TRANSLATE_TYPE) preg->translate;
-	      if (BE (range >= 0, 1))
-		{
-		  if (BE (t != NULL, 0))
-		    {
-		      while (BE (match_first < right_lim, 1)
-			     && !fastmap[t[(unsigned char) string[match_first]]])
-			++match_first;
-		    }
-		  else
-		    {
-		      while (BE (match_first < right_lim, 1)
-			     && !fastmap[(unsigned char) string[match_first]])
-			++match_first;
-		    }
-		  if (BE (match_first == right_lim, 0))
-		    {
-		      int ch = match_first >= length
-			       ? 0 : (unsigned char) string[match_first];
-		      if (!fastmap[t ? t[ch] : ch])
-			break;
-		    }
-		}
-	      else
-		{
-		  while (match_first >= left_lim)
-		    {
-		      int ch = match_first >= length
-			       ? 0 : (unsigned char) string[match_first];
-		      if (fastmap[t ? t[ch] : ch])
-			break;
-		      --match_first;
-		    }
-		  if (match_first < left_lim)
-		    break;
-		}
+	      ch = match_first >= length
+		       ? 0 : (unsigned char) string[match_first];
+	      if (!fastmap[t ? t[ch] : ch])
+		goto free_return;
 	    }
-	  else
+	  break;
+
+	case 4:
+	case 5:
+	  /* Fastmap without multi-byte translation, match backwards.  */
+	  while (match_first >= left_lim)
 	    {
-	      int ch;
+	      ch = match_first >= length
+		       ? 0 : (unsigned char) string[match_first];
+	      if (fastmap[t ? t[ch] : ch])
+		break;
+	      --match_first;
+	    }
+	  if (match_first < left_lim)
+	    goto free_return;
+	  break;
 
-	      do
+	default:
+	  /* In this case, we can't determine easily the current byte,
+	     since it might be a component byte of a multibyte
+	     character.  Then we use the constructed buffer instead.  */
+	  for (;;)
+	    {
+	      /* If MATCH_FIRST is out of the valid range, reconstruct the
+		 buffers.  */
+	      unsigned int offset = match_first - mctx.input.raw_mbs_idx;
+	      if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0))
 		{
-		  /* In this case, we can't determine easily the current byte,
-		     since it might be a component byte of a multibyte
-		     character.  Then we use the constructed buffer
-		     instead.  */
-		  /* If MATCH_FIRST is out of the valid range, reconstruct the
-		     buffers.  */
-		  if (mctx.input.raw_mbs_idx + mctx.input.valid_raw_len
-		      <= match_first
-		      || match_first < mctx.input.raw_mbs_idx)
-		    {
-		      err = re_string_reconstruct (&mctx.input, match_first,
-						   eflags);
-		      if (BE (err != REG_NOERROR, 0))
-			goto free_return;
-		    }
-		  /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
-		     Note that MATCH_FIRST must not be smaller than 0.  */
-		  ch = ((match_first >= length) ? 0
-		       : re_string_byte_at (&mctx.input,
-					    match_first
-					    - mctx.input.raw_mbs_idx));
-		  if (fastmap[ch])
-		    break;
-		  match_first += incr;
+		  err = re_string_reconstruct (&mctx.input, match_first,
+					       eflags);
+		  if (BE (err != REG_NOERROR, 0))
+		    goto free_return;
+
+		  offset = match_first - mctx.input.raw_mbs_idx;
 		}
-	      while (match_first >= left_lim && match_first <= right_lim);
-	      if (! fastmap[ch])
+	      /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
+		 Note that MATCH_FIRST must not be smaller than 0.  */
+	      ch = (match_first >= length
+		    ? 0 : re_string_byte_at (&mctx.input, offset));
+	      if (fastmap[ch])
 		break;
+	      match_first += incr;
+	      if (match_first < left_lim || match_first > right_lim)
+	        {
+	          err = REG_NOMATCH;
+	          goto free_return;
+	        }
 	    }
+	  break;
 	}
 
       /* Reconstruct the buffers so that the matcher can assume that
@@ -774,57 +787,60 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
       err = re_string_reconstruct (&mctx.input, match_first, eflags);
       if (BE (err != REG_NOERROR, 0))
 	goto free_return;
+
 #ifdef RE_ENABLE_I18N
-     /* Eliminate it when it is a component of a multibyte character
-	 and isn't the head of a multibyte character.  */
-      if (sb || re_string_first_byte (&mctx.input, 0))
+     /* Don't consider this char as a possible match start if it part,
+	yet isn't the head, of a multibyte character.  */
+      if (!sb && !re_string_first_byte (&mctx.input, 0))
+	continue;
 #endif
+
+      /* It seems to be appropriate one, then use the matcher.  */
+      /* We assume that the matching starts from 0.  */
+      mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
+      match_last = check_matching (&mctx, fl_longest_match,
+				   range >= 0 ? &match_first : NULL);
+      if (match_last != -1)
 	{
-	  /* It seems to be appropriate one, then use the matcher.  */
-	  /* We assume that the matching starts from 0.  */
-	  mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
-	  match_last = check_matching (&mctx, fl_longest_match,
-				       range >= 0 ? &match_first : NULL);
-	  if (match_last != -1)
+	  if (BE (match_last == -2, 0))
+	    {
+	      err = REG_ESPACE;
+	      goto free_return;
+	    }
+	  else
 	    {
-	      if (BE (match_last == -2, 0))
+	      mctx.match_last = match_last;
+	      if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
 		{
-		  err = REG_ESPACE;
-		  goto free_return;
+		  re_dfastate_t *pstate = mctx.state_log[match_last];
+		  mctx.last_node = check_halt_state_context (&mctx, pstate,
+							     match_last);
 		}
-	      else
+	      if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
+		  || dfa->nbackref)
 		{
-		  mctx.match_last = match_last;
-		  if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
-		    {
-		      re_dfastate_t *pstate = mctx.state_log[match_last];
-		      mctx.last_node = check_halt_state_context (&mctx, pstate,
-								 match_last);
-		    }
-		  if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
-		      || dfa->nbackref)
-		    {
-		      err = prune_impossible_nodes (&mctx);
-		      if (err == REG_NOERROR)
-			break;
-		      if (BE (err != REG_NOMATCH, 0))
-			goto free_return;
-		      match_last = -1;
-		    }
-		  else
-		    break; /* We found a match.  */
+		  err = prune_impossible_nodes (&mctx);
+		  if (err == REG_NOERROR)
+		    break;
+		  if (BE (err != REG_NOMATCH, 0))
+		    goto free_return;
+		  match_last = -1;
 		}
+	      else
+		break; /* We found a match.  */
 	    }
-	  match_ctx_clean (&mctx);
 	}
-      /* Update counter.  */
-      match_first += incr;
-      if (match_first < left_lim || right_lim < match_first)
-	break;
+
+      match_ctx_clean (&mctx);
     }
 
+#ifdef DEBUG
+  assert (match_last != -1);
+  assert (err == REG_NOERROR);
+#endif
+
   /* Set pmatch[] if we need.  */
-  if (match_last != -1 && nmatch > 0)
+  if (nmatch > 0)
     {
       int reg_idx;
 
@@ -869,7 +885,7 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
 	    pmatch[reg_idx].rm_eo += match_first;
 	  }
     }
-  err = (match_last == -1) ? REG_NOMATCH : REG_NOERROR;
+
  free_return:
   re_free (mctx.state_log);
   if (dfa->nbackref)
@@ -1072,6 +1088,20 @@ check_matching (mctx, fl_longest_match, p_match_first)
   while (!re_string_eoi (&mctx->input))
     {
       re_dfastate_t *old_state = cur_state;
+      int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
+
+      if (BE (next_char_idx >= mctx->input.bufs_len, 0)
+          || (BE (next_char_idx >= mctx->input.valid_len, 0)
+              && mctx->input.valid_len < mctx->input.len))
+        {
+          err = extend_buffers (mctx);
+          if (BE (err != REG_NOERROR, 0))
+	    {
+	      assert (err == REG_ESPACE);
+	      return -2;
+	    }
+        }
+
       cur_state = transit_state (&err, mctx, cur_state);
       if (mctx->state_log != NULL)
 	cur_state = merge_state_with_log (&err, mctx, cur_state);
@@ -1090,10 +1120,10 @@ check_matching (mctx, fl_longest_match, p_match_first)
 	    break;
 	}
 
-      if (at_init_state)
+      if (BE (at_init_state, 0))
 	{
 	  if (old_state == cur_state)
-	    next_start_idx = re_string_cur_idx (&mctx->input);
+	    next_start_idx = next_char_idx;
 	  else
 	    at_init_state = 0;
 	}
@@ -1109,13 +1139,16 @@ check_matching (mctx, fl_longest_match, p_match_first)
 	      /* We found an appropriate halt state.  */
 	      match_last = re_string_cur_idx (&mctx->input);
 	      match = 1;
+
+	      /* We found a match, do not modify match_first below.  */
+	      p_match_first = NULL;
 	      if (!fl_longest_match)
 		break;
 	    }
 	}
-   }
+    }
 
-  if (match_last == -1 && p_match_first)
+  if (p_match_first)
     *p_match_first += next_start_idx;
 
   return match_last;
@@ -2167,23 +2200,14 @@ transit_state (err, mctx, state)
   re_dfastate_t **trtable;
   unsigned char ch;
 
-  if (re_string_cur_idx (&mctx->input) + 1 >= mctx->input.bufs_len
-      || (re_string_cur_idx (&mctx->input) + 1 >= mctx->input.valid_len
-	  && mctx->input.valid_len < mctx->input.len))
+#ifdef RE_ENABLE_I18N
+  /* If the current state can accept multibyte.  */
+  if (BE (state->accept_mb, 0))
     {
-      *err = extend_buffers (mctx);
+      *err = transit_state_mb (mctx, state);
       if (BE (*err != REG_NOERROR, 0))
 	return NULL;
     }
-
-#ifdef RE_ENABLE_I18N
-      /* If the current state can accept multibyte.  */
-      if (state->accept_mb)
-	{
-	  *err = transit_state_mb (mctx, state);
-	  if (BE (*err != REG_NOERROR, 0))
-	    return NULL;
-	}
 #endif /* RE_ENABLE_I18N */
 
   /* Then decide the next state with the single byte.  */
diff --git a/posix/tst-waitid.c b/posix/tst-waitid.c
index 642d529a9a..d810922f04 100644
--- a/posix/tst-waitid.c
+++ b/posix/tst-waitid.c
@@ -18,7 +18,7 @@
    02111-1307 USA.  */
 
 #include <errno.h>
-#include <error.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/wait.h>
@@ -56,16 +56,15 @@ sigchld (int signo, siginfo_t *info, void *ctx)
 {
   if (signo != SIGCHLD)
     {
-      error (0, 0, "SIGCHLD handler got signal %d instead!", signo);
+      printf ("SIGCHLD handler got signal %d instead!\n", signo);
       _exit (EXIT_FAILURE);
     }
 
   if (! expecting_sigchld)
     {
       spurious_sigchld = 1;
-      error (0, 0,
-	     "spurious SIGCHLD: signo %d code %d status %d pid %d\n",
-	     info->si_signo, info->si_code, info->si_status, info->si_pid);
+      printf ("spurious SIGCHLD: signo %d code %d status %d pid %d\n",
+	      info->si_signo, info->si_code, info->si_status, info->si_pid);
     }
   else
     {
@@ -79,7 +78,7 @@ check_sigchld (const char *phase, int *ok, int code, int status, pid_t pid)
 {
   if (expecting_sigchld)
     {
-      error (0, 0, "missing SIGCHLD on %s", phase);
+      printf ("missing SIGCHLD on %s\n", phase);
       *ok = EXIT_FAILURE;
       expecting_sigchld = 0;
       return;
@@ -87,22 +86,22 @@ check_sigchld (const char *phase, int *ok, int code, int status, pid_t pid)
 
   if (sigchld_info.si_signo != SIGCHLD)
     {
-      error (0, 0, "SIGCHLD for %s signal %d", phase, sigchld_info.si_signo);
+      printf ("SIGCHLD for %s signal %d\n", phase, sigchld_info.si_signo);
       *ok = EXIT_FAILURE;
     }
   if (sigchld_info.si_code != code)
     {
-      error (0, 0, "SIGCHLD for %s code %d", phase, sigchld_info.si_code);
+      printf ("SIGCHLD for %s code %d\n", phase, sigchld_info.si_code);
       *ok = EXIT_FAILURE;
     }
   if (sigchld_info.si_status != status)
     {
-      error (0, 0, "SIGCHLD for %s status %d", phase, sigchld_info.si_status);
+      printf ("SIGCHLD for %s status %d\n", phase, sigchld_info.si_status);
       *ok = EXIT_FAILURE;
     }
   if (sigchld_info.si_pid != pid)
     {
-      error (0, 0, "SIGCHLD for %s pid %d", phase, sigchld_info.si_pid);
+      printf ("SIGCHLD for %s pid %d\n", phase, sigchld_info.si_pid);
       *ok = EXIT_FAILURE;
     }
 }
@@ -121,7 +120,7 @@ do_test (int argc, char *argv[])
   sa.sa_sigaction = &sigchld;
   if (sigemptyset (&sa.sa_mask) < 0 || sigaction (SIGCHLD, &sa, NULL) < 0)
     {
-      error (0, errno, "setting SIGCHLD handler");
+      printf ("setting SIGCHLD handler: %m\n");
       return EXIT_FAILURE;
     }
 #endif
@@ -131,7 +130,7 @@ do_test (int argc, char *argv[])
   pid_t pid = fork ();
   if (pid < 0)
     {
-      error (0, errno, "fork");
+      printf ("fork: %m\n");
       return EXIT_FAILURE;
     }
   else if (pid == 0)
@@ -156,18 +155,18 @@ do_test (int argc, char *argv[])
   switch (fail)
     {
     default:
-      error (0, 0, "waitid returned bogus value %d\n", fail);
+      printf ("waitid returned bogus value %d\n", fail);
       RETURN (EXIT_FAILURE);
     case -1:
-      error (0, errno, "waitid WNOHANG on stopped");
+      printf ("waitid WNOHANG on stopped: %m\n");
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
     case 0:
       if (info.si_signo == 0)
 	break;
       if (info.si_signo == SIGCHLD)
-	error (0, 0, "waitid WNOHANG on stopped status %d\n", info.si_status);
+	printf ("waitid WNOHANG on stopped status %d\n", info.si_status);
       else
-	error (0, 0, "waitid WNOHANG on stopped signal %d\n", info.si_signo);
+	printf ("waitid WNOHANG on stopped signal %d\n", info.si_signo);
       RETURN (EXIT_FAILURE);
     }
 
@@ -179,34 +178,34 @@ do_test (int argc, char *argv[])
   switch (fail)
     {
     default:
-      error (0, 0, "waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail);
+      printf ("waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail);
       RETURN (EXIT_FAILURE);
     case -1:
-      error (0, errno, "waitid WSTOPPED|WNOHANG on stopped");
+      printf ("waitid WSTOPPED|WNOHANG on stopped: %m\n");
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
-	  error (0, 0, "waitid WSTOPPED|WNOHANG on stopped signal %d\n",
-		 info.si_signo);
+	  printf ("waitid WSTOPPED|WNOHANG on stopped signal %d\n",
+		  info.si_signo);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_code != CLD_STOPPED)
 	{
-	  error (0, 0, "waitid WSTOPPED|WNOHANG on stopped code %d\n",
-		 info.si_code);
+	  printf ("waitid WSTOPPED|WNOHANG on stopped code %d\n",
+		  info.si_code);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_status != SIGSTOP)
 	{
-	  error (0, 0, "waitid WSTOPPED|WNOHANG on stopped status %d\n",
-		 info.si_status);
+	  printf ("waitid WSTOPPED|WNOHANG on stopped status %d\n",
+		  info.si_status);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_pid != pid)
 	{
-	  error (0, 0, "waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
-		 info.si_pid, pid);
+	  printf ("waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
+		  info.si_pid, pid);
 	  RETURN (EXIT_FAILURE);
 	}
     }
@@ -215,7 +214,7 @@ do_test (int argc, char *argv[])
 
   if (kill (pid, SIGCONT) != 0)
     {
-      error (0, errno, "kill (%d, SIGCONT)", pid);
+      printf ("kill (%d, SIGCONT): %m\n", pid);
       RETURN (EXIT_FAILURE);
     }
 
@@ -225,7 +224,7 @@ do_test (int argc, char *argv[])
 #if WCONTINUED != 0
   if (expecting_sigchld)
     {
-      error (0, 0, "no SIGCHLD seen for SIGCONT (optional)");
+      printf ("no SIGCHLD seen for SIGCONT (optional)\n");
       expecting_sigchld = 0;
     }
   else
@@ -238,35 +237,34 @@ do_test (int argc, char *argv[])
   switch (fail)
     {
     default:
-      error (0, 0,
-	     "waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail);
+      printf ("waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail);
       RETURN (EXIT_FAILURE);
     case -1:
-      error (0, errno, "waitid WCONTINUED|WNOWAIT on continued");
+      printf ("waitid WCONTINUED|WNOWAIT on continued: %m\n");
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
-	  error (0, 0, "waitid WCONTINUED|WNOWAIT on continued signal %d\n",
-		 info.si_signo);
+	  printf ("waitid WCONTINUED|WNOWAIT on continued signal %d\n",
+		  info.si_signo);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_code != CLD_CONTINUED)
 	{
-	  error (0, 0, "waitid WCONTINUED|WNOWAIT on continued code %d\n",
-		 info.si_code);
+	  printf ("waitid WCONTINUED|WNOWAIT on continued code %d\n",
+		  info.si_code);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_status != SIGCONT)
 	{
-	  error (0, 0, "waitid WCONTINUED|WNOWAIT on continued status %d\n",
-		 info.si_status);
+	  printf ("waitid WCONTINUED|WNOWAIT on continued status %d\n",
+		  info.si_status);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_pid != pid)
 	{
-	  error (0, 0, "waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n",
-		 info.si_pid, pid);
+	  printf ("waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n",
+		  info.si_pid, pid);
 	  RETURN (EXIT_FAILURE);
 	}
     }
@@ -279,34 +277,32 @@ do_test (int argc, char *argv[])
   switch (fail)
     {
     default:
-      error (0, 0, "waitid WCONTINUED returned bogus value %d\n", fail);
+      printf ("waitid WCONTINUED returned bogus value %d\n", fail);
       RETURN (EXIT_FAILURE);
     case -1:
-      error (0, errno, "waitid WCONTINUED on continued");
+      printf ("waitid WCONTINUED on continued: %m\n");
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
-	  error (0, 0, "waitid WCONTINUED on continued signal %d\n",
-		 info.si_signo);
+	  printf ("waitid WCONTINUED on continued signal %d\n", info.si_signo);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_code != CLD_CONTINUED)
 	{
-	  error (0, 0, "waitid WCONTINUED on continued code %d\n",
-		 info.si_code);
+	  printf ("waitid WCONTINUED on continued code %d\n", info.si_code);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_status != SIGCONT)
 	{
-	  error (0, 0, "waitid WCONTINUED on continued status %d\n",
-		 info.si_status);
+	  printf ("waitid WCONTINUED on continued status %d\n",
+		  info.si_status);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_pid != pid)
 	{
-	  error (0, 0, "waitid WCONTINUED on continued pid %d != %d\n",
-		 info.si_pid, pid);
+	  printf ("waitid WCONTINUED on continued pid %d != %d\n",
+		  info.si_pid, pid);
 	  RETURN (EXIT_FAILURE);
 	}
     }
@@ -317,22 +313,20 @@ do_test (int argc, char *argv[])
   switch (fail)
     {
     default:
-      error (0, 0, "waitid returned bogus value %d\n", fail);
+      printf ("waitid returned bogus value %d\n", fail);
       RETURN (EXIT_FAILURE);
     case -1:
-      error (0, errno, "waitid WCONTINUED|WNOHANG on waited continued");
+      printf ("waitid WCONTINUED|WNOHANG on waited continued: %m\n");
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
     case 0:
       if (info.si_signo == 0)
 	break;
       if (info.si_signo == SIGCHLD)
-	error (0, 0,
-	       "waitid WCONTINUED|WNOHANG on waited continued status %d\n",
-	       info.si_status);
+	printf ("waitid WCONTINUED|WNOHANG on waited continued status %d\n",
+		info.si_status);
       else
-	error (0, 0,
-	       "waitid WCONTINUED|WNOHANG on waited continued signal %d\n",
-	       info.si_signo);
+	printf ("waitid WCONTINUED|WNOHANG on waited continued signal %d\n",
+		info.si_signo);
       RETURN (EXIT_FAILURE);
     }
 
@@ -340,26 +334,25 @@ do_test (int argc, char *argv[])
   expecting_sigchld = 1;
   if (kill (pid, SIGSTOP) != 0)
     {
-      error (0, errno, "kill (%d, SIGSTOP)", pid);
+      printf ("kill (%d, SIGSTOP): %m\n", pid);
       RETURN (EXIT_FAILURE);
     }
   pid_t wpid = waitpid (pid, &fail, WUNTRACED);
   if (wpid < 0)
     {
-      error (0, errno, "waitpid WUNTRACED on stopped");
+      printf ("waitpid WUNTRACED on stopped: %m\n");
       RETURN (EXIT_FAILURE);
     }
   else if (wpid != pid)
     {
-      error (0, 0,
-	     "waitpid WUNTRACED on stopped returned %d != %d (status %x)",
-	     wpid, pid, fail);
+      printf ("waitpid WUNTRACED on stopped returned %d != %d (status %x)\n",
+	      wpid, pid, fail);
       RETURN (EXIT_FAILURE);
     }
   else if (!WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail)
 	   || WIFCONTINUED (fail) || WSTOPSIG (fail) != SIGSTOP)
     {
-      error (0, 0, "waitpid WUNTRACED on stopped: status %x", fail);
+      printf ("waitpid WUNTRACED on stopped: status %x\n", fail);
       RETURN (EXIT_FAILURE);
     }
   CHECK_SIGCHLD ("stopped", CLD_STOPPED, SIGSTOP);
@@ -367,7 +360,7 @@ do_test (int argc, char *argv[])
   expecting_sigchld = 1;
   if (kill (pid, SIGCONT) != 0)
     {
-      error (0, errno, "kill (%d, SIGCONT)", pid);
+      printf ("kill (%d, SIGCONT): %m\n", pid);
       RETURN (EXIT_FAILURE);
     }
 
@@ -376,7 +369,7 @@ do_test (int argc, char *argv[])
 
   if (expecting_sigchld)
     {
-      error (0, 0, "no SIGCHLD seen for SIGCONT (optional)");
+      printf ("no SIGCHLD seen for SIGCONT (optional)\n");
       expecting_sigchld = 0;
     }
   else
@@ -386,24 +379,24 @@ do_test (int argc, char *argv[])
   if (wpid < 0)
     {
       if (errno == EINVAL)
-	error (0, 0, "waitpid does not support WCONTINUED");
+	printf ("waitpid does not support WCONTINUED\n");
       else
 	{
-	  error (0, errno, "waitpid WCONTINUED on continued");
+	  printf ("waitpid WCONTINUED on continued: %m\n");
 	  RETURN (EXIT_FAILURE);
 	}
     }
   else if (wpid != pid)
     {
-      error (0, 0,
-	     "waitpid WCONTINUED on continued returned %d != %d (status %x)",
+      printf ("\
+waitpid WCONTINUED on continued returned %d != %d (status %x)\n",
 	     wpid, pid, fail);
       RETURN (EXIT_FAILURE);
     }
   else if (WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail)
 	   || !WIFCONTINUED (fail))
     {
-      error (0, 0, "waitpid WCONTINUED on continued: status %x", fail);
+      printf ("waitpid WCONTINUED on continued: status %x\n", fail);
       RETURN (EXIT_FAILURE);
     }
 #endif
@@ -413,7 +406,7 @@ do_test (int argc, char *argv[])
   /* Die, child, die!  */
   if (kill (pid, SIGKILL) != 0)
     {
-      error (0, errno, "kill (%d, SIGKILL)", pid);
+      printf ("kill (%d, SIGKILL): %m\n", pid);
       RETURN (EXIT_FAILURE);
     }
 
@@ -425,34 +418,30 @@ do_test (int argc, char *argv[])
   switch (fail)
     {
     default:
-      error (0, 0, "waitid WNOWAIT returned bogus value %d\n", fail);
+      printf ("waitid WNOWAIT returned bogus value %d\n", fail);
       RETURN (EXIT_FAILURE);
     case -1:
-      error (0, errno, "waitid WNOWAIT on killed");
+      printf ("waitid WNOWAIT on killed: %m\n");
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
-	  error (0, 0, "waitid WNOWAIT on killed signal %d\n",
-		 info.si_signo);
+	  printf ("waitid WNOWAIT on killed signal %d\n", info.si_signo);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_code != CLD_KILLED)
 	{
-	  error (0, 0, "waitid WNOWAIT on killed code %d\n",
-		 info.si_code);
+	  printf ("waitid WNOWAIT on killed code %d\n", info.si_code);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_status != SIGKILL)
 	{
-	  error (0, 0, "waitid WNOWAIT on killed status %d\n",
-		 info.si_status);
+	  printf ("waitid WNOWAIT on killed status %d\n", info.si_status);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_pid != pid)
 	{
-	  error (0, 0, "waitid WNOWAIT on killed pid %d != %d\n",
-		 info.si_pid, pid);
+	  printf ("waitid WNOWAIT on killed pid %d != %d\n", info.si_pid, pid);
 	  RETURN (EXIT_FAILURE);
 	}
     }
@@ -470,34 +459,30 @@ do_test (int argc, char *argv[])
   switch (fail)
     {
     default:
-      error (0, 0, "waitid WNOHANG returned bogus value %d\n", fail);
+      printf ("waitid WNOHANG returned bogus value %d\n", fail);
       RETURN (EXIT_FAILURE);
     case -1:
-      error (0, errno, "waitid WNOHANG on killed");
+      printf ("waitid WNOHANG on killed: %m\n");
       RETURN (EXIT_FAILURE);
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
-	  error (0, 0, "waitid WNOHANG on killed signal %d\n",
-		 info.si_signo);
+	  printf ("waitid WNOHANG on killed signal %d\n", info.si_signo);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_code != CLD_KILLED)
 	{
-	  error (0, 0, "waitid WNOHANG on killed code %d\n",
-		 info.si_code);
+	  printf ("waitid WNOHANG on killed code %d\n", info.si_code);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_status != SIGKILL)
 	{
-	  error (0, 0, "waitid WNOHANG on killed status %d\n",
-		 info.si_status);
+	  printf ("waitid WNOHANG on killed status %d\n", info.si_status);
 	  RETURN (EXIT_FAILURE);
 	}
       if (info.si_pid != pid)
 	{
-	  error (0, 0, "waitid WNOHANG on killed pid %d != %d\n",
-		 info.si_pid, pid);
+	  printf ("waitid WNOHANG on killed pid %d != %d\n", info.si_pid, pid);
 	  RETURN (EXIT_FAILURE);
 	}
     }
@@ -507,13 +492,13 @@ do_test (int argc, char *argv[])
     {
       if (errno != ECHILD)
 	{
-	  error (0, errno, "waitid WEXITED on killed");
+	  printf ("waitid WEXITED on killed: %m\n");
 	  RETURN (EXIT_FAILURE);
 	}
     }
   else
     {
-      error (0, 0, "waitid WEXITED returned bogus value %d\n", fail);
+      printf ("waitid WEXITED returned bogus value %d\n", fail);
       RETURN (EXIT_FAILURE);
     }