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

📄 histexpand.c

📁 在非GUI环境下
💻 C
📖 第 1 页 / 共 3 页
字号:
	  return (0);	}    }  /* Extract and perform the substitution. */  for (passc = dquote = i = j = 0; i < l; i++)    {      int tchar = string[i];      if (passc)	{	  passc = 0;	  ADD_CHAR (tchar);	  continue;	}#if defined (HANDLE_MULTIBYTE)      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)	{	  int k, c;	  c = tchar;	  memset (mb, 0, sizeof (mb));	  for (k = 0; k < MB_LEN_MAX; k++)	    {	      mb[k] = (char)c;	      memset (&ps, 0, sizeof (mbstate_t));	      if (_rl_get_char_len (mb, &ps) == -2)		c = string[++i];	      else		break;	    }	  if (strlen (mb) > 1)	    {	      ADD_STRING (mb);	      break;	    }	}#endif /* HANDLE_MULTIBYTE */      if (tchar == history_expansion_char)	tchar = -3;      else if (tchar == history_comment_char)	tchar = -2;      switch (tchar)	{	default:	  ADD_CHAR (string[i]);	  break;	case '\\':	  passc++;	  ADD_CHAR (tchar);	  break;	case '"':	  dquote = 1 - dquote;	  ADD_CHAR (tchar);	  break;	  	case '\'':	  {	    /* If history_quotes_inhibit_expansion is set, single quotes	       inhibit history expansion. */	    if (dquote == 0 && history_quotes_inhibit_expansion)	      {		int quote, slen;		quote = i++;		hist_string_extract_single_quoted (string, &i);		slen = i - quote + 2;		temp = (char *)xmalloc (slen);		strncpy (temp, string + quote, slen);		temp[slen - 1] = '\0';		ADD_STRING (temp);		free (temp);	      }	    else	      ADD_CHAR (string[i]);	    break;	  }	case -2:		/* history_comment_char */	  if (i == 0 || member (string[i - 1], history_word_delimiters))	    {	      temp = (char *)xmalloc (l - i + 1);	      strcpy (temp, string + i);	      ADD_STRING (temp);	      free (temp);	      i = l;	    }	  else	    ADD_CHAR (string[i]);	  break;	case -3:		/* history_expansion_char */	  cc = string[i + 1];	  /* If the history_expansion_char is followed by one of the	     characters in history_no_expand_chars, then it is not a	     candidate for expansion of any kind. */	  if (member (cc, history_no_expand_chars))	    {	      ADD_CHAR (string[i]);	      break;	    }#if defined (NO_BANG_HASH_MODIFIERS)	  /* There is something that is listed as a `word specifier' in csh	     documentation which means `the expanded text to this point'.	     That is not a word specifier, it is an event specifier.  If we	     don't want to allow modifiers with `!#', just stick the current	     output line in again. */	  if (cc == '#')	    {	      if (result)		{		  temp = (char *)xmalloc (1 + strlen (result));		  strcpy (temp, result);		  ADD_STRING (temp);		  free (temp);		}	      i++;	      break;	    }#endif	  r = history_expand_internal (string, i, &eindex, &temp, result);	  if (r < 0)	    {	      *output = temp;	      free (result);	      if (string != hstring)		free (string);	      return -1;	    }	  else	    {	      if (temp)		{		  modified++;		  if (*temp)		    ADD_STRING (temp);		  free (temp);		}	      only_printing = r == 1;	      i = eindex;	    }	  break;	}    }  *output = result;  if (string != hstring)    free (string);  if (only_printing)    {#if 0      add_history (result);#endif      return (2);    }  return (modified != 0);}/* Return a consed string which is the word specified in SPEC, and found   in FROM.  NULL is returned if there is no spec.  The address of   ERROR_POINTER is returned if the word specified cannot be found.   CALLER_INDEX is the offset in SPEC to start looking; it is updated   to point to just after the last character parsed. */static char *get_history_word_specifier (spec, from, caller_index)     char *spec, *from;     int *caller_index;{  register int i = *caller_index;  int first, last;  int expecting_word_spec = 0;  char *result;  /* The range of words to return doesn't exist yet. */  first = last = 0;  result = (char *)NULL;  /* If we found a colon, then this *must* be a word specification.  If     it isn't, then it is an error. */  if (spec[i] == ':')    {      i++;      expecting_word_spec++;    }  /* Handle special cases first. */  /* `%' is the word last searched for. */  if (spec[i] == '%')    {      *caller_index = i + 1;      return (search_match ? savestring (search_match) : savestring (""));    }  /* `*' matches all of the arguments, but not the command. */  if (spec[i] == '*')    {      *caller_index = i + 1;      result = history_arg_extract (1, '$', from);      return (result ? result : savestring (""));    }  /* `$' is last arg. */  if (spec[i] == '$')    {      *caller_index = i + 1;      return (history_arg_extract ('$', '$', from));    }  /* Try to get FIRST and LAST figured out. */  if (spec[i] == '-')    first = 0;  else if (spec[i] == '^')    {      first = 1;      i++;    }  else if (_rl_digit_p (spec[i]) && expecting_word_spec)    {      for (first = 0; _rl_digit_p (spec[i]); i++)	first = (first * 10) + _rl_digit_value (spec[i]);    }  else    return ((char *)NULL);	/* no valid `first' for word specifier */  if (spec[i] == '^' || spec[i] == '*')    {      last = (spec[i] == '^') ? 1 : '$';	/* x* abbreviates x-$ */      i++;    }  else if (spec[i] != '-')    last = first;  else    {      i++;      if (_rl_digit_p (spec[i]))	{	  for (last = 0; _rl_digit_p (spec[i]); i++)	    last = (last * 10) + _rl_digit_value (spec[i]);	}      else if (spec[i] == '$')	{	  i++;	  last = '$';	}#if 0      else if (!spec[i] || spec[i] == ':')	/* check against `:' because there could be a modifier separator */#else      else	/* csh seems to allow anything to terminate the word spec here,	   leaving it as an abbreviation. */#endif	last = -1;		/* x- abbreviates x-$ omitting word `$' */    }  *caller_index = i;  if (last >= first || last == '$' || last < 0)    result = history_arg_extract (first, last, from);  return (result ? result : (char *)&error_pointer);}/* Extract the args specified, starting at FIRST, and ending at LAST.   The args are taken from STRING.  If either FIRST or LAST is < 0,   then make that arg count from the right (subtract from the number of   tokens, so that FIRST = -1 means the next to last token on the line).   If LAST is `$' the last arg from STRING is used. */char *history_arg_extract (first, last, string)     int first, last;     const char *string;{  register int i, len;  char *result;  int size, offset;  char **list;  /* XXX - think about making history_tokenize return a struct array,     each struct in array being a string and a length to avoid the     calls to strlen below. */  if ((list = history_tokenize (string)) == NULL)    return ((char *)NULL);  for (len = 0; list[len]; len++)    ;  if (last < 0)    last = len + last - 1;  if (first < 0)    first = len + first - 1;  if (last == '$')    last = len - 1;  if (first == '$')    first = len - 1;  last++;  if (first >= len || last > len || first < 0 || last < 0 || first > last)    result = ((char *)NULL);  else    {      for (size = 0, i = first; i < last; i++)	size += strlen (list[i]) + 1;      result = (char *)xmalloc (size + 1);      result[0] = '\0';      for (i = first, offset = 0; i < last; i++)	{	  strcpy (result + offset, list[i]);	  offset += strlen (list[i]);	  if (i + 1 < last)	    {      	      result[offset++] = ' ';	      result[offset] = 0;	    }	}    }  for (i = 0; i < len; i++)    free (list[i]);  free (list);  return (result);}static inthistory_tokenize_word (string, ind)     const char *string;     int ind;{  register int i;  int delimiter;  i = ind;  delimiter = 0;  if (member (string[i], "()\n"))    {      i++;      return i;    }  if (member (string[i], "<>;&|$"))    {      int peek = string[i + 1];      if (peek == string[i] && peek != '$')	{	  if (peek == '<' && string[i + 2] == '-')	    i++;	  i += 2;	  return i;	}      else	{	  if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||	      (peek == '>' && string[i] == '&') ||	      (peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */	      (peek == '(' && string[i] == '$')) /* ) */	    {	      i += 2;	      return i;	    }	}      if (string[i] != '$')	{	  i++;	  return i;	}    }  /* Get word from string + i; */  if (member (string[i], HISTORY_QUOTE_CHARACTERS))    delimiter = string[i++];  for (; string[i]; i++)    {      if (string[i] == '\\' && string[i + 1] == '\n')	{	  i++;	  continue;	}      if (string[i] == '\\' && delimiter != '\'' &&	  (delimiter != '"' || member (string[i], slashify_in_quotes)))	{	  i++;	  continue;	}      if (delimiter && string[i] == delimiter)	{	  delimiter = 0;	  continue;	}      if (!delimiter && (member (string[i], history_word_delimiters)))	break;      if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))	delimiter = string[i];    }  return i;}static char *history_substring (string, start, end)     const char *string;     int start, end;{  register int len;  register char *result;  len = end - start;  result = (char *)xmalloc (len + 1);  strncpy (result, string + start, len);  result[len] = '\0';  return result;}/* Parse STRING into tokens and return an array of strings.  If WIND is   not -1 and INDP is not null, we also want the word surrounding index   WIND.  The position in the returned array of strings is returned in   *INDP. */static char **history_tokenize_internal (string, wind, indp)     const char *string;     int wind, *indp;{  char **result;  register int i, start, result_index, size;  /* If we're searching for a string that's not part of a word (e.g., " "),     make sure we set *INDP to a reasonable value. */  if (indp && wind != -1)    *indp = -1;  /* Get a token, and stuff it into RESULT.  The tokens are split     exactly where the shell would split them. */  for (i = result_index = size = 0, result = (char **)NULL; string[i]; )    {      /* Skip leading whitespace. */      for (; string[i] && whitespace (string[i]); i++)	;      if (string[i] == 0 || string[i] == history_comment_char)	return (result);      start = i;      i = history_tokenize_word (string, start);      /* If we have a non-whitespace delimiter character (which would not be	 skipped by the loop above), use it and any adjacent delimiters to	 make a separate field.  Any adjacent white space will be skipped the	 next time through the loop. */      if (i == start && history_word_delimiters)	{	  i++;	  while (string[i] && member (string[i], history_word_delimiters))	    i++;	}      /* If we are looking for the word in which the character at a	 particular index falls, remember it. */      if (indp && wind != -1 && wind >= start && wind < i)        *indp = result_index;      if (result_index + 2 >= size)	result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));      result[result_index++] = history_substring (string, start, i);      result[result_index] = (char *)NULL;    }  return (result);}/* Return an array of tokens, much as the shell might.  The tokens are   parsed out of STRING. */char **history_tokenize (string)     const char *string;{  return (history_tokenize_internal (string, -1, (int *)NULL));}/* Find and return the word which contains the character at index IND   in the history line LINE.  Used to save the word matched by the   last history !?string? search. */static char *history_find_word (line, ind)     char *line;     int ind;{  char **words, *s;  int i, wind;  words = history_tokenize_internal (line, ind, &wind);  if (wind == -1 || words == 0)    return ((char *)NULL);  s = words[wind];  for (i = 0; i < wind; i++)    free (words[i]);  for (i = wind + 1; words[i]; i++)    free (words[i]);  free (words);  return s;}

⌨️ 快捷键说明

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