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

📄 histexpand.c

📁 在非GUI环境下
💻 C
📖 第 1 页 / 共 3 页
字号:
  result = (char *)xmalloc (result_len = 128);  i = start;  /* If it is followed by something that starts a word specifier,     then !! is implied as the event specifier. */  if (member (string[i + 1], ":$*%^"))    {      char fake_s[3];      int fake_i = 0;      i++;      fake_s[0] = fake_s[1] = history_expansion_char;      fake_s[2] = '\0';      event = get_history_event (fake_s, &fake_i, 0);    }  else if (string[i + 1] == '#')    {      i += 2;      event = current_line;    }  else    {      int quoted_search_delimiter = 0;      /* If the character before this `!' is a double or single	 quote, then this expansion takes place inside of the	 quoted string.  If we have to search for some text ("!foo"),	 allow the delimiter to end the search string. */#if defined (HANDLE_MULTIBYTE)      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)	{	  int c, l;	  l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY);	  c = string[l];	  /* XXX - original patch had i - 1 ???  If i == 0 it would fail. */	  if (i && (c == '\'' || c == '"'))	    quoted_search_delimiter = c;	}      else#endif /* HANDLE_MULTIBYTE */	  	if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))	  quoted_search_delimiter = string[i - 1];      event = get_history_event (string, &i, quoted_search_delimiter);    }	    if (event == 0)    {      *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);      free (result);      return (-1);    }  /* If a word specifier is found, then do what that requires. */  starting_index = i;  word_spec = get_history_word_specifier (string, event, &i);  /* There is no such thing as a `malformed word specifier'.  However,     it is possible for a specifier that has no match.  In that case,     we complain. */  if (word_spec == (char *)&error_pointer)    {      *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);      free (result);      return (-1);    }  /* If no word specifier, than the thing of interest was the event. */  temp = word_spec ? savestring (word_spec) : savestring (event);  FREE (word_spec);  /* Perhaps there are other modifiers involved.  Do what they say. */  want_quotes = substitute_globally = subst_bywords = print_only = 0;  starting_index = i;  while (string[i] == ':')    {      c = string[i + 1];      if (c == 'g' || c == 'a')	{	  substitute_globally = 1;	  i++;	  c = string[i + 1];	}      else if (c == 'G')	{	  subst_bywords = 1;	  i++;	  c = string[i + 1];	}      switch (c)	{	default:	  *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);	  free (result);	  free (temp);	  return -1;	case 'q':	  want_quotes = 'q';	  break;	case 'x':	  want_quotes = 'x';	  break;	  /* :p means make this the last executed line.  So we	     return an error state after adding this line to the	     history. */	case 'p':	  print_only++;	  break;	  /* :t discards all but the last part of the pathname. */	case 't':	  tstr = strrchr (temp, '/');	  if (tstr)	    {	      tstr++;	      t = savestring (tstr);	      free (temp);	      temp = t;	    }	  break;	  /* :h discards the last part of a pathname. */	case 'h':	  tstr = strrchr (temp, '/');	  if (tstr)	    *tstr = '\0';	  break;	  /* :r discards the suffix. */	case 'r':	  tstr = strrchr (temp, '.');	  if (tstr)	    *tstr = '\0';	  break;	  /* :e discards everything but the suffix. */	case 'e':	  tstr = strrchr (temp, '.');	  if (tstr)	    {	      t = savestring (tstr);	      free (temp);	      temp = t;	    }	  break;	/* :s/this/that substitutes `that' for the first	   occurrence of `this'.  :gs/this/that substitutes `that'	   for each occurrence of `this'.  :& repeats the last	   substitution.  :g& repeats the last substitution	   globally. */	case '&':	case 's':	  {	    char *new_event;	    int delimiter, failed, si, l_temp, ws, we;	    if (c == 's')	      {		if (i + 2 < (int)strlen (string))		  {#if defined (HANDLE_MULTIBYTE)		    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)		      {			_rl_adjust_point (string, i + 2, &ps);			if (_rl_get_char_len (string + i + 2, &ps) > 1)			  delimiter = 0;			else			  delimiter = string[i + 2];		      }		    else#endif /* HANDLE_MULTIBYTE */		      delimiter = string[i + 2];		  }		else		  break;	/* no search delimiter */		i += 3;		t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);		/* An empty substitution lhs with no previous substitution		   uses the last search string as the lhs. */		if (t)		  {		    FREE (subst_lhs);		    subst_lhs = t;		  }		else if (!subst_lhs)		  {		    if (search_string && *search_string)		      {			subst_lhs = savestring (search_string);			subst_lhs_len = strlen (subst_lhs);		      }		    else		      {			subst_lhs = (char *) NULL;			subst_lhs_len = 0;		      }		  }		FREE (subst_rhs);		subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);		/* If `&' appears in the rhs, it's supposed to be replaced		   with the lhs. */		if (member ('&', subst_rhs))		  postproc_subst_rhs ();	      }	    else	      i += 2;	    /* If there is no lhs, the substitution can't succeed. */	    if (subst_lhs_len == 0)	      {		*ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);		free (result);		free (temp);		return -1;	      }	    l_temp = strlen (temp);	    /* Ignore impossible cases. */	    if (subst_lhs_len > l_temp)	      {		*ret_string = hist_error (string, starting_index, i, SUBST_FAILED);		free (result);		free (temp);		return (-1);	      }	    /* Find the first occurrence of THIS in TEMP. */	    /* Substitute SUBST_RHS for SUBST_LHS in TEMP.  There are three	       cases to consider:		 1.  substitute_globally == subst_bywords == 0		 2.  substitute_globally == 1 && subst_bywords == 0		 3.  substitute_globally == 0 && subst_bywords == 1	       In the first case, we substitute for the first occurrence only.	       In the second case, we substitute for every occurrence.	       In the third case, we tokenize into words and substitute the	       first occurrence of each word. */	    si = we = 0;	    for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)	      {		/* First skip whitespace and find word boundaries if		   we're past the end of the word boundary we found		   the last time. */		if (subst_bywords && si > we)		  {		    for (; temp[si] && whitespace (temp[si]); si++)		      ;		    ws = si;		    we = history_tokenize_word (temp, si);		  }		if (STREQN (temp+si, subst_lhs, subst_lhs_len))		  {		    int len = subst_rhs_len - subst_lhs_len + l_temp;		    new_event = (char *)xmalloc (1 + len);		    strncpy (new_event, temp, si);		    strncpy (new_event + si, subst_rhs, subst_rhs_len);		    strncpy (new_event + si + subst_rhs_len,			     temp + si + subst_lhs_len,			     l_temp - (si + subst_lhs_len));		    new_event[len] = '\0';		    free (temp);		    temp = new_event;		    failed = 0;		    if (substitute_globally)		      {			/* Reported to fix a bug that causes it to skip every			   other match when matching a single character.  Was			   si += subst_rhs_len previously. */			si += subst_rhs_len - 1;			l_temp = strlen (temp);			substitute_globally++;			continue;		      }		    else if (subst_bywords)		      {			si = we;			l_temp = strlen (temp);			continue;		      }		    else		      break;		  }	      }	    if (substitute_globally > 1)	      {		substitute_globally = 0;		continue;	/* don't want to increment i */	      }	    if (failed == 0)	      continue;		/* don't want to increment i */	    *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);	    free (result);	    free (temp);	    return (-1);	  }	}      i += 2;    }  /* Done with modfiers. */  /* Believe it or not, we have to back the pointer up by one. */  --i;  if (want_quotes)    {      char *x;      if (want_quotes == 'q')	x = sh_single_quote (temp);      else if (want_quotes == 'x')	x = quote_breaks (temp);      else	x = savestring (temp);      free (temp);      temp = x;    }  n = strlen (temp);  if (n >= result_len)    result = (char *)xrealloc (result, n + 2);  strcpy (result, temp);  free (temp);  *end_index_ptr = i;  *ret_string = result;  return (print_only);}/* Expand the string STRING, placing the result into OUTPUT, a pointer   to a string.  Returns:  -1) If there was an error in expansion.   0) If no expansions took place (or, if the only change in      the text was the de-slashifying of the history expansion      character)   1) If expansions did take place   2) If the `p' modifier was given and the caller should print the result  If an error ocurred in expansion, then OUTPUT contains a descriptive  error message. */#define ADD_STRING(s) \	do \	  { \	    int sl = strlen (s); \	    j += sl; \	    if (j >= result_len) \	      { \		while (j >= result_len) \		  result_len += 128; \		result = (char *)xrealloc (result, result_len); \	      } \	    strcpy (result + j - sl, s); \	  } \	while (0)#define ADD_CHAR(c) \	do \	  { \	    if (j >= result_len - 1) \	      result = (char *)xrealloc (result, result_len += 64); \	    result[j++] = c; \	    result[j] = '\0'; \	  } \	while (0)inthistory_expand (hstring, output)     char *hstring;     char **output;{  register int j;  int i, r, l, passc, cc, modified, eindex, only_printing, dquote;  char *string;  /* The output string, and its length. */  int result_len;  char *result;#if defined (HANDLE_MULTIBYTE)  char mb[MB_LEN_MAX];  mbstate_t ps;#endif  /* Used when adding the string. */  char *temp;  if (output == 0)    return 0;  /* Setting the history expansion character to 0 inhibits all     history expansion. */  if (history_expansion_char == 0)    {      *output = savestring (hstring);      return (0);    }      /* Prepare the buffer for printing error messages. */  result = (char *)xmalloc (result_len = 256);  result[0] = '\0';  only_printing = modified = 0;  l = strlen (hstring);  /* Grovel the string.  Only backslash and single quotes can quote the     history escape character.  We also handle arg specifiers. */  /* Before we grovel forever, see if the history_expansion_char appears     anywhere within the text. */  /* The quick substitution character is a history expansion all right.  That     is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,     that is the substitution that we do. */  if (hstring[0] == history_subst_char)    {      string = (char *)xmalloc (l + 5);      string[0] = string[1] = history_expansion_char;      string[2] = ':';      string[3] = 's';      strcpy (string + 4, hstring);      l += 4;    }  else    {#if defined (HANDLE_MULTIBYTE)      memset (&ps, 0, sizeof (mbstate_t));#endif      string = hstring;      /* If not quick substitution, still maybe have to do expansion. */      /* `!' followed by one of the characters in history_no_expand_chars	 is NOT an expansion. */      for (i = dquote = 0; string[i]; i++)	{#if defined (HANDLE_MULTIBYTE)	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)	    {	      int v;	      v = _rl_get_char_len (string + i, &ps);	      if (v > 1)		{		  i += v - 1;		  continue;		}	    }#endif /* HANDLE_MULTIBYTE */	  cc = string[i + 1];	  /* The history_comment_char, if set, appearing at the beginning	     of a word signifies that the rest of the line should not have	     history expansion performed on it.	     Skip the rest of the line and break out of the loop. */	  if (history_comment_char && string[i] == history_comment_char &&	      (i == 0 || member (string[i - 1], history_word_delimiters)))	    {	      while (string[i])		i++;	      break;	    }	  else if (string[i] == history_expansion_char)	    {	      if (!cc || member (cc, history_no_expand_chars))		continue;	      /* If the calling application has set		 history_inhibit_expansion_function to a function that checks		 for special cases that should not be history expanded,		 call the function and skip the expansion if it returns a		 non-zero value. */	      else if (history_inhibit_expansion_function &&			(*history_inhibit_expansion_function) (string, i))		continue;	      else		break;	    }	  /* Shell-like quoting: allow backslashes to quote double quotes	     inside a double-quoted string. */	  else if (dquote && string[i] == '\\' && cc == '"')	    i++;	  /* More shell-like quoting:  if we're paying attention to single	     quotes and letting them quote the history expansion character,	     then we need to pay attention to double quotes, because single	     quotes are not special inside double-quoted strings. */	  else if (history_quotes_inhibit_expansion && string[i] == '"')	    {	      dquote = 1 - dquote;	    }	  else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'')	    {	      /* If this is bash, single quotes inhibit history expansion. */	      i++;	      hist_string_extract_single_quoted (string, &i);	    }	  else if (history_quotes_inhibit_expansion && string[i] == '\\')	    {	      /* If this is bash, allow backslashes to quote single		 quotes and the history expansion character. */	      if (cc == '\'' || cc == history_expansion_char)		i++;	    }	  	}	        if (string[i] != history_expansion_char)	{	  free (result);	  *output = savestring (string);

⌨️ 快捷键说明

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