substitute (struct obstack *obs, const char *victim, const char *repl,
	    struct re_registers *regs)
{
  int ch;

  for (;;)
    {
      while ((ch = *repl++) != '\\')
	{
	  if (ch == '\0')
	    return;
	  obstack_1grow (obs, ch);
	}

      switch ((ch = *repl++))
	{
	case '0':
	  if (!substitute_warned)
	    {
	      M4ERROR ((warning_status, 0, "\
Warning: \\0 will disappear, use \\& instead in replacements"));
	      substitute_warned = 1;
	    }
	  /* Fall through.  */

	case '&':
	  obstack_grow (obs, victim + regs->start[0],
			regs->end[0] - regs->start[0]);
	  break;

	case '1': case '2': case '3': case '4': case '5': case '6':
	case '7': case '8': case '9':
	  ch -= '0';
	  if (regs->num_regs - 1 <= ch)
	    M4ERROR ((warning_status, 0,
		      "Warning: sub-expression %d not present", ch));
	  else if (regs->end[ch] > 0)
	    obstack_grow (obs, victim + regs->start[ch],
			  regs->end[ch] - regs->start[ch]);
	  break;

	case '\0':
	  M4ERROR ((warning_status, 0,
		    "Warning: trailing \\ ignored in replacement"));
	  return;

	default:
	  obstack_1grow (obs, ch);
	  break;
	}
    }
}
substitute (struct obstack *obs, const char *victim, const char *repl,
	    struct re_registers *regs)
{
  int ch;

  for (;;)
    {
      while ((ch = *repl++) != '\\')
	{
	  if (ch == '\0')
	    return;
	  obstack_1grow (obs, ch);
	}

      switch ((ch = *repl++))
	{
	case '0':
	  if (!substitute_warned)
	    {
	      M4ERROR ((warning_status, 0, "\
Warning: \\0 will disappear, use \\& instead in replacements"));
	      substitute_warned = 1;
	    }
	   

	case '&':
	  obstack_grow (obs, victim + regs->start[0],
			regs->end[0] - regs->start[0]);
	  break;

	case '1': case '2': case '3': case '4': case '5': case '6':
	case '7': case '8': case '9':
	  ch -= '0';
	  if (regs->num_regs - 1 <= ch)
	    M4ERROR ((warning_status, 0,
		      "Warning: sub-expression %d not present", ch));
	  else if (regs->end[ch] > 0)
	    obstack_grow (obs, victim + regs->start[ch],
			  regs->end[ch] - regs->start[ch]);
	  break;

	case '\0':
	  M4ERROR ((warning_status, 0,
		    "Warning: trailing \\ ignored in replacement"));
	  return;

	default:
	  obstack_1grow (obs, ch);
	  break;
	}
    }
}