⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iwordexp.c

📁 Intercom 是一个 Unix系统上灵活的语音传输软件。支持标准音频压缩比如GSM, G.711, and G.72x和其他音频编码。Intercom专为高速网络设计来传输高品质的语音
💻 C
📖 第 1 页 / 共 4 页
字号:
  size_t env_maxlen;  size_t pat_length;  size_t pat_maxlen;  size_t start = *offset;  char *env;  char *pattern;  char *value = NULL;  enum action action = ACT_NONE;  int depth = 0;  int colon_seen = 0;  int seen_hash = 0;  int free_value = 0;  int pattern_is_quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */  int error;  int special = 0;  char buffer[21];  int brace = words[*offset] == '{';  env = w_newword (&env_length, &env_maxlen);  pattern = w_newword (&pat_length, &pat_maxlen);  if (brace)    ++*offset;  /* First collect the parameter name. */  if (words[*offset] == '#')    {      seen_hash = 1;      if (!brace)	goto envsubst;      ++*offset;    }  if (isalpha (words[*offset]) || words[*offset] == '_')    {      /* Normal parameter name. */      do	{	  env = w_addchar (env, &env_length, &env_maxlen,			   words[*offset]);	  if (env == NULL)	    goto no_space;	}      while (isalnum (words[++*offset]) || words[*offset] == '_');    }  else if (isdigit (words[*offset]))    {      /* Numeric parameter name. */      special = 1;      do	{	  env = w_addchar (env, &env_length, &env_maxlen,			   words[*offset]);	  if (env == NULL)	    goto no_space;	  if (!brace)	    goto envsubst;	}      while (isdigit(words[++*offset]));    }  else if (strchr ("*@$", words[*offset]) != NULL)    {      /* Special parameter. */      special = 1;      env = w_addchar (env, &env_length, &env_maxlen,		       words[*offset]);      if (env == NULL)	goto no_space;      ++*offset;    }  else    {      if (brace)	goto syntax;    }  if (brace)    {      /* Check for special action to be applied to the value. */      switch (words[*offset])	{	case '}':	  /* Evaluate. */	  goto envsubst;	case '#':	  action = ACT_RP_SHORT_LEFT;	  if (words[1 + *offset] == '#')	    {	      ++*offset;	      action = ACT_RP_LONG_LEFT;	    }	  break;	case '%':	  action = ACT_RP_SHORT_RIGHT;	  if (words[1 + *offset] == '%')	    {	      ++*offset;	      action = ACT_RP_LONG_RIGHT;	    }	  break;	case ':':	  if (strchr ("-=?+", words[1 + *offset]) == NULL)	    goto syntax;	  colon_seen = 1;	  action = words[++*offset];	  break;	case '-':	case '=':	case '?':	case '+':	  action = words[*offset];	  break;	default:	  goto syntax;	}      /* Now collect the pattern, but don't expand it yet. */      ++*offset;      for (; words[*offset]; ++(*offset))	{	  switch (words[*offset])	    {	    case '{':	      if (!pattern_is_quoted)		++depth;	      break;	    case '}':	      if (!pattern_is_quoted)		{		  if (depth == 0)		    goto envsubst;		  --depth;		}	      break;	    case '\\':	      if (pattern_is_quoted)		/* Quoted; treat as normal character. */		break;	      /* Otherwise, it's an escape: next character is literal. */	      if (words[++*offset] == '\0')		goto syntax;	      pattern = w_addchar (pattern, &pat_length, &pat_maxlen, '\\');	      if (pattern == NULL)		goto no_space;	      break;	    case '\'':	      if (pattern_is_quoted == 0)		pattern_is_quoted = 1;	      else if (pattern_is_quoted == 1)		pattern_is_quoted = 0;	      break;	    case '"':	      if (pattern_is_quoted == 0)		pattern_is_quoted = 2;	      else if (pattern_is_quoted == 2)		pattern_is_quoted = 0;	      break;	    }	  pattern = w_addchar (pattern, &pat_length, &pat_maxlen,			       words[*offset]);	  if (pattern == NULL)	    goto no_space;	}    }  /* End of input string -- remember to reparse the character that we   * stopped at.  */  --(*offset);envsubst:  if (words[start] == '{' && words[*offset] != '}')    goto syntax;  if (env == NULL)    {      if (seen_hash)	{	  /* $# expands to the number of positional parameters */	  buffer[20] = '\0';	  value = itoa_word (0, &buffer[20], 10, 0);	  seen_hash = 0;	}      else	{	  /* Just $ on its own */	  *offset = start - 1;	  *word = w_addchar (*word, word_length, max_length, '$');	  return *word ? 0 : WRDE_NOSPACE;	}    }  /* Is it a special parameter? */  else if (special)    {      /* Is it `$$'? */      if (*env == '$')	{	  buffer[20] = '\0';	  value = itoa_word (getpid (), &buffer[20], 10, 0);	}    }  else    value = getenv (env);  if (value == NULL && (flags & WRDE_UNDEF))    {      /* Variable not defined. */      error = WRDE_BADVAL;      goto do_error;    }  if (action != ACT_NONE)    {      int expand_pattern = 0;      /* First, find out if we need to expand pattern (i.e. if we will       * use it). */      switch (action)	{	case ACT_RP_SHORT_LEFT:	case ACT_RP_LONG_LEFT:	case ACT_RP_SHORT_RIGHT:	case ACT_RP_LONG_RIGHT:	  /* Always expand for these. */	  expand_pattern = 1;	  break;	case ACT_NULL_ERROR:	case ACT_NULL_SUBST:	case ACT_NULL_ASSIGN:	  if (!value || (!*value && colon_seen))	    /* If param is unset, or set but null and a colon has been seen,	       the expansion of the pattern will be needed. */	    expand_pattern = 1;	  break;	case ACT_NONNULL_SUBST:	  /* Expansion of word will be needed if parameter is set and not null,	     or set null but no colon has been seen. */	  if (value && (*value || !colon_seen))	    expand_pattern = 1;	  break;	default:	  assert (! "Unrecognised action!");	}      if (expand_pattern)	{	  /* We need to perform tilde expansion, parameter expansion,             command substitution, and arithmetic expansion.  We also	     have to be a bit careful with wildcard characters, as	     pattern might be given to fnmatch soon.  To do this, we	     convert quotes to escapes. */	  char *expanded;	  size_t exp_len;	  size_t exp_maxl;	  char *p;	  int quoted = 0; /* 1: single quotes; 2: double */	  expanded = w_newword (&exp_len, &exp_maxl);	  for (p = pattern; p && *p; p++)	    {	      size_t offset;	      switch (*p)		{		case '"':		  if (quoted == 2)		    quoted = 0;		  else if (quoted == 0)		    quoted = 2;		  else break;		  continue;		case '\'':		  if (quoted == 1)		    quoted = 0;		  else if (quoted == 0)		    quoted = 1;		  else break;		  continue;		case '*':		case '?':		  if (quoted)		    {		      /* Convert quoted wildchar to escaped wildchar. */		      expanded = w_addchar (expanded, &exp_len,					    &exp_maxl, '\\');		      if (expanded == NULL)			goto no_space;		    }		  break;		case '$':		  offset = 0;		  error = parse_dollars (&expanded, &exp_len, &exp_maxl, p,					 &offset, flags, NULL, NULL, NULL, 1);		  if (error)		    {		      if (free_value)			free (value);		      if (expanded)			free (expanded);		      goto do_error;		    }		  p += offset;		  continue;		case '~':		  if (quoted || exp_len)		    break;		  offset = 0;		  error = parse_tilde (&expanded, &exp_len, &exp_maxl, p,				       &offset, 0);		  if (error)		    {		      if (free_value)			free (value);		      if (expanded)			free (expanded);		      goto do_error;		    }		  p += offset;		  continue;		case '\\':		  expanded = w_addchar (expanded, &exp_len, &exp_maxl, '\\');		  ++p;		  assert (*p); /* checked when extracted initially */		  if (expanded == NULL)		    goto no_space;		}	      expanded = w_addchar (expanded, &exp_len, &exp_maxl, *p);	      if (expanded == NULL)		goto no_space;	    }	  if (pattern)		  free (pattern);	  pattern = expanded;	}      switch (action)	{	case ACT_RP_SHORT_LEFT:	case ACT_RP_LONG_LEFT:	case ACT_RP_SHORT_RIGHT:	case ACT_RP_LONG_RIGHT:	  {	    char *p;	    char c;	    char *end;	    if (value == NULL || pattern == NULL || *pattern == '\0')	      break;	    end = value + strlen (value);	    switch (action)	      {	      case ACT_RP_SHORT_LEFT:		for (p = value; p <= end; ++p)		  {		    c = *p;		    *p = '\0';		    if (fnmatch (pattern, value, 0) != FNM_NOMATCH)		      {			*p = c;			if (free_value)			  {			    char *newval = strdup (p);			    if (newval == NULL)			      {				free (value);				goto no_space;			      }			    free (value);			    value = newval;			  }			else			  value = p;			break;		      }		    *p = c;		  }		break;	      case ACT_RP_LONG_LEFT:		for (p = end; p >= value; --p)		  {		    c = *p;		    *p = '\0';		    if (fnmatch (pattern, value, 0) != FNM_NOMATCH)		      {			*p = c;			if (free_value)			  {			    char *newval = strdup (p);			    if (newval == NULL)			      {				free (value);				goto no_space;			      }			    free (value);			    value = newval;			  }			else			  value = p;			break;		      }		    *p = c;		  }		break;	      case ACT_RP_SHORT_RIGHT:		for (p = end; p >= value; --p)		  {		    if (fnmatch (pattern, p, 0) != FNM_NOMATCH)		      {			char *newval;			newval = malloc (p - value + 1);			if (newval == NULL)			  {			    if (free_value)			      free (value);			    goto no_space;			  }			*(char *) mempcpy (newval, value, p - value) = '\0';			if (free_value)			  free (value);			value = newval;			free_value = 1;			break;		      }		  }		break;	      case ACT_RP_LONG_RIGHT:		for (p = value; p <= end; ++p)		  {		    if (fnmatch (pattern, p, 0) != FNM_NOMATCH)		      {			char *newval;			newval = malloc (p - value + 1);			if (newval == NULL)			  {			    if (free_value)			      free (value);			    goto no_space;			  }			*(char *) mempcpy (newval, value, p - value) = '\0';			if (free_value)			  free (value);			value = newval;			free_value = 1;			break;		      }		  }		break;	      default:		break;	      }	    break;	  }	case ACT_NULL_ERROR:	  if (value && *value)	    /* Substitute parameter */	    break;	  error = 0;	  if (!colon_seen && value)	    /* Substitute NULL */	    ;	  else	    {	      const char *str = pattern;	      if (str[0] == '\0')		str = _("parameter null or not set");#ifdef USE_IN_LIBIO	      if (_IO_fwide (stderr, 0) > 0)		fwprintf (stderr, L"%s: %s\n", env, str);	      else#endif		fprintf (stderr, "%s: %s\n", env, str);	    }	  if (free_value)	    free (value);	  goto do_error;	case ACT_NULL_SUBST:	  if (value && *value)	    /* Substitute parameter */	    break;	  if (free_value && value)	    free (value);	  if (!colon_seen && value)	    /* Substitute NULL */	    goto success;	  value = pattern ? strdup (pattern) : pattern;	  free_value = 1;	  if (pattern && !value)	    goto no_space;	  break;	case ACT_NONNULL_SUBST:	  if (value && (*value || !colon_seen))	    {	      if (free_value && value)		free (value);	      value = pattern ? strdup (pattern) : pattern;	      free_value = 1;	      if (pattern && !value)		goto no_space;	      break;	    }	  /* Substitute NULL */	  if (free_value)	    free (value);	  goto success;	case ACT_NULL_ASSIGN:	  if (value && *value)	    /* Substitute parameter */	    break;	  if (!colon_seen && value)	    {	      /* Substitute NULL */	      if (free_value)		free (value);	      goto success;	    }	  if (free_value && value)	    free (value);	  value = pattern ? strdup (pattern) : pattern;	  free_value = 1;	  if (pattern && !value)	    goto no_space;	  setenv (env, value, 1);	  break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -