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

📄 history.c

📁 linux下bash的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    {      int tchar = string[i];      if (passc)	{	  passc = 0;	  ADD_CHAR (tchar);	  continue;	}      if (tchar == history_expansion_char)	tchar = -3;      switch (tchar)	{	default:	  ADD_CHAR (string[i]);	  break;	case '\\':	  passc++;	  ADD_CHAR (tchar);	  break;#if defined (SHELL)	case '\'':	  {	    /* If this is bash, single quotes inhibit history expansion. */	    int quote, slen;	    quote = i++;	    rl_string_extract_single_quoted (string, &i);	    slen = i - quote + 2;	    temp = xmalloc (slen);	    strncpy (temp, string + quote, slen);	    temp[slen - 1] = '\0';	    ADD_STRING (temp);	    free (temp);	    break;	  }#endif /* SHELL */	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 = 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)    {      add_history (result);      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;  else if (digit_p (spec[i]) && expecting_word_spec)    {      for (first = 0; digit_p (spec[i]); i++)	first = (first * 10) + 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 (digit_p (spec[i]))	{	  for (last = 0; digit_p (spec[i]); i++)	    last = (last * 10) + digit_value (spec[i]);	}      else if (spec[i] == '$')	{	  i++;	  last = '$';	}      else if (!spec[i] || spec[i] == ':')  /* could be modifier separator */	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;     char *string;{  register int i, len;  char *result = (char *)NULL;  int size = 0, offset = 0;  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 = xmalloc (size + 1);      result[0] = '\0';      for (i = first; 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);}#define slashify_in_quotes "\\`\"$"/* 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)     char *string;     int wind, *indp;{  char **result = (char **)NULL;  register int i, start, result_index, size;  int len;  i = result_index = size = 0;  /* Get a token, and stuff it into RESULT.  The tokens are split     exactly where the shell would split them. */  while (string[i])    {      int delimiter = 0;      /* Skip leading whitespace. */      for (; string[i] && whitespace (string[i]); i++)	;      if (!string[i] || string[i] == history_comment_char)	return (result);      start = i;            if (member (string[i], "()\n"))	{	  i++;	  goto got_token;	}      if (member (string[i], "<>;&|$"))	{	  int peek = string[i + 1];	  if (peek == string[i] && peek != '$')	    {	      if (peek == '<' && string[i + 2] == '-')		i++;	      i += 2;	      goto got_token;	    }	  else	    {	      if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||		  ((peek == '>') && (string[i] == '&')) ||		  ((peek == '(') && (string[i] == '$')))		{		  i += 2;		  goto got_token;		}	    }	  if (string[i] != '$')	    {	      i++;	      goto got_token;	    }	}      /* Get word from string + i; */      if (member (string[i], "\"'`"))	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], " \t\n;&()|<>")))	    break;	  if (!delimiter && member (string[i], "\"'`"))	    delimiter = string[i];	}    got_token:      /* If we are looking for the word in which the character at a	 particular index falls, remember it. */      if (indp && wind >= 0 && wind >= start && wind < i)        *indp = result_index;      len = i - start;      if (result_index + 2 >= size)	result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));      result[result_index] = xmalloc (1 + len);      strncpy (result[result_index], string + start, len);      result[result_index][len] = '\0';      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)     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)    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;}#if defined (STATIC_MALLOC)/* **************************************************************** *//*								    *//*			xmalloc and xrealloc ()		     	    *//*								    *//* **************************************************************** */static void memory_error_and_abort ();static char *xmalloc (bytes)     int bytes;{  char *temp = (char *)malloc (bytes);  if (!temp)    memory_error_and_abort ();  return (temp);}static char *xrealloc (pointer, bytes)     char *pointer;     int bytes;{  char *temp;  if (!pointer)    temp = (char *)xmalloc (bytes);  else    temp = (char *)realloc (pointer, bytes);  if (!temp)    memory_error_and_abort ();  return (temp);}static voidmemory_error_and_abort (){  fprintf (stderr, "history: Out of virtual memory!\n");  abort ();}#endif /* STATIC_MALLOC *//* **************************************************************** *//*								    *//*				Test Code			    *//*								    *//* **************************************************************** */#ifdef TESTmain (){  char line[1024], *t;  int done = 0;  line[0] = 0;  while (!done)    {      fprintf (stdout, "history%% ");      t = gets (line);      if (!t)	strcpy (line, "quit");      if (line[0])	{	  char *expansion;	  int result;	  using_history ();	  result = history_expand (line, &expansion);	  strcpy (line, expansion);	  free (expansion);	  if (result)	    fprintf (stderr, "%s\n", line);	  if (result < 0)	    continue;	  add_history (line);	}      if (strcmp (line, "quit") == 0) done = 1;      if (strcmp (line, "save") == 0) write_history (0);      if (strcmp (line, "read") == 0) read_history (0);      if (strcmp (line, "list") == 0)	{	  register HIST_ENTRY **the_list = history_list ();	  register int i;	  if (the_list)	    for (i = 0; the_list[i]; i++)	      fprintf (stdout, "%d: %s\n", i + history_base, the_list[i]->line);	}      if (strncmp (line, "delete", strlen ("delete")) == 0)	{	  int which;	  if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1)	    {	      HIST_ENTRY *entry = remove_history (which);	      if (!entry)		fprintf (stderr, "No such entry %d\n", which);	      else		{		  free (entry->line);		  free (entry);		}	    }	  else	    {	      fprintf (stderr, "non-numeric arg given to `delete'\n");	    }	}    }}#endif /* TEST *//** Local variables:* compile-command: "gcc -g -DTEST -o history history.c"* end:*/

⌨️ 快捷键说明

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