fieldsplit_this_word = 0;  if (words[words_offset] == '\0')  goto end_of_string;
wordexp (const char *words, wordexp_t *pwordexp, int flags){  size_t wordv_offset;  size_t words_offset;  size_t word_length;  size_t max_length;  char *word = w_newword (&word_length, &max_length);  int error;  char *ifs;  char ifs_white[4];  char **old_wordv = pwordexp->we_wordv;  size_t old_wordc = (flags & WRDE_REUSE) ? pwordexp->we_wordc : 0;  int fieldsplit_this_word = 0;  if (flags & WRDE_REUSE)    {      /* Minimal implementation of WRDE_REUSE for now */      wordfree (pwordexp);      old_wordv = NULL;    }  if (flags & WRDE_DOOFFS)    {      pwordexp->we_wordv = calloc (1 + pwordexp->we_offs, sizeof (char *));      if (pwordexp->we_wordv == NULL)	{	  error = WRDE_NOSPACE;	  goto do_error;	}    }  else    {      pwordexp->we_wordv = calloc (1, sizeof (char *));      if (pwordexp->we_wordv == NULL)	{	  error = WRDE_NOSPACE;	  goto do_error;	}      pwordexp->we_offs = 0;    }  if ((flags & WRDE_APPEND) == 0)    pwordexp->we_wordc = 0;  wordv_offset = pwordexp->we_offs + pwordexp->we_wordc;  /* Find out what the field separators are.   * There are two types: whitespace and non-whitespace.   */  ifs = getenv ("IFS");  if (!ifs)    /* IFS unset - use <space><tab><newline>. */    ifs = strcpy (ifs_white, " \t\n");  else    {      char *ifsch = ifs;      char *whch = ifs_white;      /* Start off with no whitespace IFS characters */      ifs_white[0] = '\0';      while (*ifsch != '\0')	{	  if ((*ifsch == ' ') || (*ifsch == '\t') || (*ifsch == '\n'))	    {	      /* Whitespace IFS.  See first whether it is already in our		 collection.  */	      char *runp = ifs_white;	      while (runp < whch && *runp != '\0' && *runp != *ifsch)		++runp;	      if (runp == whch)		*whch++ = *ifsch;	    }	  ++ifsch;	}      *whch = '\0';    }  fieldsplit_this_word = 0;  for (words_offset = 0 ; ; ++words_offset)    switch (words[words_offset])      {      case '\\':	error = parse_backslash (&word, &word_length, &max_length, words,				 &words_offset);	if (error)	  goto do_error;	break;      case '$':	error = parse_dollars (&word, &word_length, &max_length, words,			       &words_offset, flags, pwordexp, ifs, ifs_white,			       0, &fieldsplit_this_word);	if (error)	  goto do_error;	break;      case '`':	if (flags & WRDE_NOCMD)	  {	    error = WRDE_CMDSUB;	    goto do_error;	  }	++words_offset;	error = parse_backtick (&word, &word_length, &max_length, words,				&words_offset, flags, pwordexp, ifs,				ifs_white);	if (error)	  goto do_error;	fieldsplit_this_word = 1;	break;      case '"':	++words_offset;	error = parse_dquote (&word, &word_length, &max_length, words,			      &words_offset, flags, pwordexp, ifs, ifs_white);	if (error)	  goto do_error;	break;      case '\'':	++words_offset;	error = parse_squote (&word, &word_length, &max_length, words,			      &words_offset);	if (error)	  goto do_error;	break;      case '~':	error = parse_tilde (&word, &word_length, &max_length, words,			     &words_offset, pwordexp->we_wordc);	if (error)	  goto do_error;	break;      case '*':      case '[':      case '?':	error = parse_glob (&word, &word_length, &max_length, words,			    &words_offset, flags, pwordexp, ifs, ifs_white);	if (error)	  goto do_error;	break;      default:	/* Is it a word separator? */	if (words[words_offset] != '\0' &&	    strchr (" \t", words[words_offset]) == NULL)	  {	    char ch = words[words_offset];	    /* Not a word separator -- but is it a valid word char? */	    if (strchr ("\n|&;<>(){}", ch))	      {		/* Fail */		wordfree (pwordexp);		pwordexp->we_wordc = 0;		pwordexp->we_wordv = old_wordv;		return WRDE_BADCHAR;	      }	    /* "Ordinary" character -- add it to word */	    word = w_addchar (word, &word_length, &max_length,			      ch);	    if (word == NULL)	      {		error = WRDE_NOSPACE;		goto do_error;	      }	    break;	  }	/* If a word has been delimited, add it to the list. */	if (word != NULL)	  {	    if (fieldsplit_this_word)	      {		error = field_split_word (word, pwordexp, ifs, ifs_white);		free (word);	      }	    else	      error = w_addword (pwordexp, word);	    if (error)	      goto do_error;	  }	fieldsplit_this_word = 0;	if (words[words_offset] == '\0')	  /* End of string. */	  goto end_of_string;	word = w_newword (&word_length, &max_length);      }end_of_string:  return 0;do_error:  /* Error:   *	free memory used (unless error is WRDE_NOSPACE), and   *	set we_wordc and wd_wordv back to what they were.   */  if (word != NULL)    free (word);  if (error == WRDE_NOSPACE)    return WRDE_NOSPACE;  wordfree (pwordexp);  pwordexp->we_wordv = old_wordv;  pwordexp->we_wordc = old_wordc;  return error;}