rem: if (!class_ok[(int) class_s1][(int) class_s2])
add: if ((class_s1 == UL_NONE) != (class_s2 == UL_NONE))
context: main (int argc, char **argv){  int c;  int non_option_args;  struct Spec_list buf1, buf2;  struct Spec_list *s1 = &buf1;  struct Spec_list *s2 = &buf2;  program_name = argv[0];  setlocale (LC_ALL, "");  bindtextdomain (PACKAGE, LOCALEDIR);  textdomain (PACKAGE);  atexit (close_stdout);  while ((c = getopt_long (argc, argv, "cdst", long_options, NULL)) != -1)    {      switch (c)	{	case 0:	  break;	case 'c':	  complement = 1;	  break;	case 'd':	  delete = 1;	  break;	case 's':	  squeeze_repeats = 1;	  break;	case 't':	  truncate_set1 = 1;	  break;	case_GETOPT_HELP_CHAR;	case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);	default:	  usage (2);	  break;	}    }  posix_pedantic = (getenv ("POSIXLY_CORRECT") != NULL);  non_option_args = argc - optind;  translating = (non_option_args == 2 && !delete);  /* Change this test if it is valid to give tr no options and     no args at all.  POSIX doesn't specifically say anything     either way, but it looks like they implied it's invalid     by omission.  If you want to make tr do a slow imitation     of `cat' use `tr a a'.  */  if (non_option_args > 2)    {      error (0, 0, _("too many arguments"));      usage (2);    }  if (!delete && !squeeze_repeats && non_option_args != 2)    error (EXIT_FAILURE, 0, _("two strings must be given when translating"));  if (delete && squeeze_repeats && non_option_args != 2)    error (EXIT_FAILURE, 0, _("two strings must be given when both \deleting and squeezing repeats"));  /* If --delete is given without --squeeze-repeats, then     only one string argument may be specified.  But POSIX     says to ignore any string2 in this case, so if POSIXLY_CORRECT     is set, pretend we never saw string2.  But I think     this deserves a fatal error, so that's the default.  */  if ((delete && !squeeze_repeats) && non_option_args != 1)    {      if (posix_pedantic && non_option_args == 2)	--non_option_args;      else	error (EXIT_FAILURE, 0,	       _("only one string may be given when deleting \without squeezing repeats"));    }  if (squeeze_repeats && non_option_args == 0)    error (EXIT_FAILURE, 0,	   _("at least one string must be given when squeezing repeats"));  spec_init (s1);  if (parse_str ((unsigned char *) argv[optind], s1))    exit (EXIT_FAILURE);  if (non_option_args == 2)    {      spec_init (s2);      if (parse_str ((unsigned char *) argv[optind + 1], s2))	exit (EXIT_FAILURE);    }  else    s2 = NULL;  validate (s1, s2);  /* Use binary I/O, since `tr' is sometimes used to transliterate     non-printable characters, or characters which are stripped away     by text-mode reads (like CR and ^Z).  */  SET_BINARY2 (STDIN_FILENO, STDOUT_FILENO);  if (squeeze_repeats && non_option_args == 1)    {      set_initialize (s1, complement, in_squeeze_set);      squeeze_filter (io_buf, IO_BUF_SIZE, NULL);    }  else if (delete && non_option_args == 1)    {      size_t nr;      set_initialize (s1, complement, in_delete_set);      do	{	  nr = read_and_delete (io_buf, IO_BUF_SIZE, NULL);	  if (nr > 0 && fwrite ((char *) io_buf, 1, nr, stdout) == 0)	    error (EXIT_FAILURE, errno, _("write error"));	}      while (nr > 0);    }  else if (squeeze_repeats && delete && non_option_args == 2)    {      set_initialize (s1, complement, in_delete_set);      set_initialize (s2, 0, in_squeeze_set);      squeeze_filter (io_buf, IO_BUF_SIZE, read_and_delete);    }  else if (translating)    {      if (complement)	{	  int i;	  SET_TYPE *in_s1 = in_delete_set;	  set_initialize (s1, 0, in_s1);	  s2->state = BEGIN_STATE;	  for (i = 0; i < N_CHARS; i++)	    xlate[i] = i;	  for (i = 0; i < N_CHARS; i++)	    {	      if (!in_s1[i])		{		  int ch = get_next (s2, NULL);		  assert (ch != -1 || truncate_set1);		  if (ch == -1)		    {		      /* This will happen when tr is invoked like e.g.		         tr -cs A-Za-z0-9 '\012'.  */		      break;		    }		  xlate[i] = ch;		}	    }	  assert (get_next (s2, NULL) == -1 || truncate_set1);	}      else	{	  int c1, c2;	  int i;	  enum Upper_Lower_class class_s1;	  enum Upper_Lower_class class_s2;	  for (i = 0; i < N_CHARS; i++)	    xlate[i] = i;	  s1->state = BEGIN_STATE;	  s2->state = BEGIN_STATE;	  for (;;)	    {	      c1 = get_next (s1, &class_s1);	      c2 = get_next (s2, &class_s2);	      if (!class_ok[(int) class_s1][(int) class_s2])		error (EXIT_FAILURE, 0,		       _("misaligned [:upper:] and/or [:lower:] construct"));	      if (class_s1 == UL_LOWER && class_s2 == UL_UPPER)		{		  for (i = 0; i < N_CHARS; i++)		    if (ISLOWER (i))		      xlate[i] = toupper (i);		}	      else if (class_s1 == UL_UPPER && class_s2 == UL_LOWER)		{		  for (i = 0; i < N_CHARS; i++)		    if (ISUPPER (i))		      xlate[i] = tolower (i);		}	      else if ((class_s1 == UL_LOWER && class_s2 == UL_LOWER)		       || (class_s1 == UL_UPPER && class_s2 == UL_UPPER))		{		  /* By default, GNU tr permits the identity mappings: from		     [:upper:] to [:upper:] and [:lower:] to [:lower:].  But		     when POSIXLY_CORRECT is set, those evoke diagnostics.  */		  if (posix_pedantic)		    {		      error (EXIT_FAILURE, 0,			     _("\invalid identity mapping;  when translating, any [:lower:] or [:upper:]\n\construct in string1 must be aligned with a corresponding construct\n\([:upper:] or [:lower:], respectively) in string2"));		    }		}	      else		{		  /* The following should have been checked by validate...  */		  if (c1 == -1 || c2 == -1)		    break;		  xlate[c1] = c2;		}	    }	  assert (c1 == -1 || truncate_set1);	}      if (squeeze_repeats)	{	  set_initialize (s2, 0, in_squeeze_set);	  squeeze_filter (io_buf, IO_BUF_SIZE, read_and_xlate);	}      else	{	  size_t bytes_read;	  do	    {	      bytes_read = read_and_xlate (io_buf, IO_BUF_SIZE, NULL);	      if (bytes_read > 0		  && fwrite ((char *) io_buf, 1, bytes_read, stdout) == 0)		error (EXIT_FAILURE, errno, _("write error"));	    }	  while (bytes_read > 0);	}    }  if (close (STDIN_FILENO) != 0)    error (EXIT_FAILURE, errno, _("standard input"));  exit (EXIT_SUCCESS);}