rem: } while (*mode_string == ',');
add: if (*mode_string != ',') break; }
context: mode_compile (const char *mode_string, unsigned int masked_ops){  struct mode_change *head;	/* First element of the linked list. */  struct mode_change *tail;	/* An element of the linked list. */  unsigned long octal_value;	/* The mode value, if octal.  */  mode_t umask_value;		/* The umask value (surprise). */  head = NULL;#ifdef lint  tail = NULL;#endif  if (xstrtoul (mode_string, NULL, 8, &octal_value, "") == LONGINT_OK)    {      struct mode_change *p;      mode_t mode;      if (octal_value != (octal_value & ALLM))	return MODE_INVALID;      /* Help the compiler optimize the usual case where mode_t uses	 the traditional octal representation.  */      mode = ((S_ISUID == SUID && S_ISGID == SGID && S_ISVTX == SVTX	       && S_IRUSR == RUSR && S_IWUSR == WUSR && S_IXUSR == XUSR	       && S_IRGRP == RGRP && S_IWGRP == WGRP && S_IXGRP == XGRP	       && S_IROTH == ROTH && S_IWOTH == WOTH && S_IXOTH == XOTH)	      ? octal_value	      : (mode_t) ((octal_value & SUID ? S_ISUID : 0)			  | (octal_value & SGID ? S_ISGID : 0)			  | (octal_value & SVTX ? S_ISVTX : 0)			  | (octal_value & RUSR ? S_IRUSR : 0)			  | (octal_value & WUSR ? S_IWUSR : 0)			  | (octal_value & XUSR ? S_IXUSR : 0)			  | (octal_value & RGRP ? S_IRGRP : 0)			  | (octal_value & WGRP ? S_IWGRP : 0)			  | (octal_value & XGRP ? S_IXGRP : 0)			  | (octal_value & ROTH ? S_IROTH : 0)			  | (octal_value & WOTH ? S_IWOTH : 0)			  | (octal_value & XOTH ? S_IXOTH : 0)));      p = make_node_op_equals (mode);      if (p == NULL)	return MODE_MEMORY_EXHAUSTED;      mode_append_entry (&head, &tail, p);      return head;    }  umask_value = umask (0);  umask (umask_value);		/* Restore the old value. */  --mode_string;  /* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */  do    {      /* Which bits in the mode are operated on. */      mode_t affected_bits = 0;      /* `affected_bits' modified by umask. */      mode_t affected_masked;      /* Operators to actually use umask on. */      unsigned ops_to_mask = 0;      int who_specified_p;      affected_bits = 0;      ops_to_mask = 0;      /* Turn on all the bits in `affected_bits' for each group given. */      for (++mode_string;; ++mode_string)	switch (*mode_string)	  {	  case 'u':	    affected_bits |= S_ISUID | S_IRWXU;	    break;	  case 'g':	    affected_bits |= S_ISGID | S_IRWXG;	    break;	  case 'o':	    affected_bits |= S_ISVTX | S_IRWXO;	    break;	  case 'a':	    affected_bits |= CHMOD_MODE_BITS;	    break;	  default:	    goto no_more_affected;	  }    no_more_affected:      /* If none specified, affect all bits, except perhaps those	 set in the umask. */      if (affected_bits)	who_specified_p = 1;      else	{	  who_specified_p = 0;	  affected_bits = CHMOD_MODE_BITS;	  ops_to_mask = masked_ops;	}      while (*mode_string == '=' || *mode_string == '+' || *mode_string == '-')	{	  struct mode_change *change = talloc (struct mode_change);	  if (change == NULL)	    {	      mode_free (head);	      return MODE_MEMORY_EXHAUSTED;	    }	  change->next = NULL;	  change->op = *mode_string;	/* One of "=+-". */	  affected_masked = affected_bits;	  /* Per the Single Unix Spec, if `who' is not specified and the	     `=' operator is used, then clear all the bits first.  */	  if (!who_specified_p &&	      ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS : 0))	    {	      struct mode_change *p = make_node_op_equals (0);	      if (p == NULL)		return MODE_MEMORY_EXHAUSTED;	      mode_append_entry (&head, &tail, p);	    }	  if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS			     : *mode_string == '+' ? MODE_MASK_PLUS			     : MODE_MASK_MINUS))	    affected_masked &= ~umask_value;	  change->affected = affected_masked;	  change->value = 0;	  change->flags = 0;	  /* Add the element to the tail of the list, so the operations	     are performed in the correct order. */	  mode_append_entry (&head, &tail, change);	  /* Set `value' according to the bits set in `affected_masked'. */	  for (++mode_string;; ++mode_string)	    switch (*mode_string)	      {	      case 'r':		change->value |= ((S_IRUSR | S_IRGRP | S_IROTH)				  & affected_masked);		break;	      case 'w':		change->value |= ((S_IWUSR | S_IWGRP | S_IWOTH)				  & affected_masked);		break;	      case 'X':		change->flags |= MODE_X_IF_ANY_X;		/* Fall through. */	      case 'x':		change->value |= ((S_IXUSR | S_IXGRP | S_IXOTH)				  & affected_masked);		break;	      case 's':		/* Set the setuid/gid bits if `u' or `g' is selected. */		change->value |= (S_ISUID | S_ISGID) & affected_masked;		break;	      case 't':		/* Set the "save text image" bit if `o' is selected. */		change->value |= S_ISVTX & affected_masked;		break;	      case 'u':		/* Set the affected bits to the value of the `u' bits		   on the same file.  */		if (change->value)		  goto invalid;		change->value = S_IRWXU;		change->flags |= MODE_COPY_EXISTING;		break;	      case 'g':		/* Set the affected bits to the value of the `g' bits		   on the same file.  */		if (change->value)		  goto invalid;		change->value = S_IRWXG;		change->flags |= MODE_COPY_EXISTING;		break;	      case 'o':		/* Set the affected bits to the value of the `o' bits		   on the same file.  */		if (change->value)		  goto invalid;		change->value = S_IRWXO;		change->flags |= MODE_COPY_EXISTING;		break;	      default:		goto no_more_values;	      }	no_more_values:;	}  } while (*mode_string == ',');  if (*mode_string == 0)    return head;invalid:  mode_free (head);  return MODE_INVALID;}