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

📄 readline.c

📁 UNIX下SH的实现源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* readline.c -- a general facility for reading lines of input
   with emacs style editing and completion. */

/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.

   This file is part of the GNU Readline Library, a library for
   reading lines of text with interactive input and history editing.

   The GNU Readline Library is free software; you can redistribute it
   and/or modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2, or
   (at your option) any later version.

   The GNU Readline Library is distributed in the hope that it will be
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#define READLINE_LIBRARY

#if defined (HAVE_CONFIG_H)
#  include <config.h>
#endif

#include <sys/types.h>
#include "posixstat.h"
#include <fcntl.h>
#if defined (HAVE_SYS_FILE_H)
#  include <sys/file.h>
#endif /* HAVE_SYS_FILE_H */

#if defined (HAVE_UNISTD_H)
#  include <unistd.h>
#endif /* HAVE_UNISTD_H */

#if defined (HAVE_STDLIB_H)
#  include <stdlib.h>
#else
#  include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */

#if defined (HAVE_LOCALE_H)
#  include <locale.h>
#endif

#include <stdio.h>
#include "posixjmp.h"

/* System-specific feature definitions and include files. */
#include "rldefs.h"

#if defined (__EMX__)
#  define INCL_DOSPROCESS
#  include <os2.h>
#endif /* __EMX__ */

/* Some standard library routines. */
#include "readline.h"
#include "history.h"

#include "rlprivate.h"
#include "rlshell.h"
#include "xmalloc.h"

#ifndef RL_LIBRARY_VERSION
#  define RL_LIBRARY_VERSION "4.1"
#endif

/* Evaluates its arguments multiple times. */
#define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)

/* Forward declarations used in this file. */
void _rl_free_history_entry __P((HIST_ENTRY *));

static char *readline_internal __P((void));
static void readline_initialize_everything __P((void));
static void start_using_history __P((void));
static void bind_arrow_keys __P((void));
static int rl_change_case __P((int, int));

static void readline_default_bindings __P((void));

/* **************************************************************** */
/*								    */
/*			Line editing input utility		    */
/*								    */
/* **************************************************************** */

char *rl_library_version = RL_LIBRARY_VERSION;

int rl_gnu_readline_p = 1;

/* A pointer to the keymap that is currently in use.
   By default, it is the standard emacs keymap. */
Keymap _rl_keymap = emacs_standard_keymap;

/* The current style of editing. */
int rl_editing_mode = emacs_mode;

/* Non-zero if we called this function from _rl_dispatch().  It's present
   so functions can find out whether they were called from a key binding
   or directly from an application. */
int rl_dispatching;

/* Non-zero if the previous command was a kill command. */
int _rl_last_command_was_kill = 0;

/* The current value of the numeric argument specified by the user. */
int rl_numeric_arg = 1;

/* Non-zero if an argument was typed. */
int rl_explicit_arg = 0;

/* Temporary value used while generating the argument. */
int rl_arg_sign = 1;

/* Non-zero means we have been called at least once before. */
static int rl_initialized;

/* If non-zero, this program is running in an EMACS buffer. */
static int running_in_emacs;

/* The current offset in the current input line. */
int rl_point;

/* Mark in the current input line. */
int rl_mark;

/* Length of the current input line. */
int rl_end;

/* Make this non-zero to return the current input_line. */
int rl_done;

/* The last function executed by readline. */
Function *rl_last_func = (Function *)NULL;

/* Top level environment for readline_internal (). */
procenv_t readline_top_level;

/* The streams we interact with. */
FILE *_rl_in_stream, *_rl_out_stream;

/* The names of the streams that we do input and output to. */
FILE *rl_instream = (FILE *)NULL;
FILE *rl_outstream = (FILE *)NULL;

/* Non-zero means echo characters as they are read. */
int readline_echoing_p = 1;

/* Current prompt. */
char *rl_prompt;
int rl_visible_prompt_length = 0;

/* Set to non-zero by calling application if it has already printed rl_prompt
   and does not want readline to do it the first time. */
int rl_already_prompted = 0;

/* The number of characters read in order to type this complete command. */
int rl_key_sequence_length = 0;

/* If non-zero, then this is the address of a function to call just
   before readline_internal_setup () prints the first prompt. */
Function *rl_startup_hook = (Function *)NULL;

/* If non-zero, this is the address of a function to call just before
   readline_internal_setup () returns and readline_internal starts
   reading input characters. */
Function *rl_pre_input_hook = (Function *)NULL;

/* What we use internally.  You should always refer to RL_LINE_BUFFER. */
static char *the_line;

/* The character that can generate an EOF.  Really read from
   the terminal driver... just defaulted here. */
int _rl_eof_char = CTRL ('D');

/* Non-zero makes this the next keystroke to read. */
int rl_pending_input = 0;

/* Pointer to a useful terminal name. */
char *rl_terminal_name = (char *)NULL;

/* Non-zero means to always use horizontal scrolling in line display. */
int _rl_horizontal_scroll_mode = 0;

/* Non-zero means to display an asterisk at the starts of history lines
   which have been modified. */
int _rl_mark_modified_lines = 0;  

/* The style of `bell' notification preferred.  This can be set to NO_BELL,
   AUDIBLE_BELL, or VISIBLE_BELL. */
int _rl_bell_preference = AUDIBLE_BELL;
     
/* String inserted into the line by rl_insert_comment (). */
char *_rl_comment_begin;

/* Keymap holding the function currently being executed. */
Keymap rl_executing_keymap;

/* Non-zero means to erase entire line, including prompt, on empty input lines. */
int rl_erase_empty_line = 0;

/* Non-zero means to read only this many characters rather than up to a
   character bound to accept-line. */
int rl_num_chars_to_read;

/* Line buffer and maintenence. */
char *rl_line_buffer = (char *)NULL;
int rl_line_buffer_len = 0;

/* Forward declarations used by the display and termcap code. */

/* **************************************************************** */
/*								    */
/*			`Forward' declarations  		    */
/*								    */
/* **************************************************************** */

/* Non-zero means do not parse any lines other than comments and
   parser directives. */
unsigned char _rl_parsing_conditionalized_out = 0;

/* Non-zero means to convert characters with the meta bit set to
   escape-prefixed characters so we can indirect through
   emacs_meta_keymap or vi_escape_keymap. */
int _rl_convert_meta_chars_to_ascii = 1;

/* Non-zero means to output characters with the meta bit set directly
   rather than as a meta-prefixed escape sequence. */
int _rl_output_meta_chars = 0;

/* **************************************************************** */
/*								    */
/*			Top Level Functions			    */
/*								    */
/* **************************************************************** */

/* Non-zero means treat 0200 bit in terminal input as Meta bit. */
int _rl_meta_flag = 0;	/* Forward declaration */

/* Read a line of input.  Prompt with PROMPT.  An empty PROMPT means
   none.  A return value of NULL means that EOF was encountered. */
char *
readline (prompt)
     char *prompt;
{
  char *value;

  rl_prompt = prompt;

  /* If we are at EOF return a NULL string. */
  if (rl_pending_input == EOF)
    {
      rl_pending_input = 0;
      return ((char *)NULL);
    }

  rl_visible_prompt_length = rl_expand_prompt (rl_prompt);

  rl_initialize ();
  (*rl_prep_term_function) (_rl_meta_flag);

#if defined (HANDLE_SIGNALS)
  rl_set_signals ();
#endif

  value = readline_internal ();
  (*rl_deprep_term_function) ();

#if defined (HANDLE_SIGNALS)
  rl_clear_signals ();
#endif

  return (value);
}

#if defined (READLINE_CALLBACKS)
#  define STATIC_CALLBACK
#else
#  define STATIC_CALLBACK static
#endif

STATIC_CALLBACK void
readline_internal_setup ()
{
  char *nprompt;

  _rl_in_stream = rl_instream;
  _rl_out_stream = rl_outstream;

  if (rl_startup_hook)
    (*rl_startup_hook) ();

  if (readline_echoing_p == 0)
    {
      if (rl_prompt && rl_already_prompted == 0)
	{
	  nprompt = _rl_strip_prompt (rl_prompt);
	  fprintf (_rl_out_stream, "%s", nprompt);
	  fflush (_rl_out_stream);
	  free (nprompt);
	}
    }
  else
    {
      if (rl_prompt && rl_already_prompted)
	rl_on_new_line_with_prompt ();
      else
	rl_on_new_line ();
      (*rl_redisplay_function) ();
#if defined (VI_MODE)
      if (rl_editing_mode == vi_mode)
	rl_vi_insertion_mode (1, 0);
#endif /* VI_MODE */
    }

  if (rl_pre_input_hook)
    (*rl_pre_input_hook) ();
}

STATIC_CALLBACK char *
readline_internal_teardown (eof)
     int eof;
{
  char *temp;
  HIST_ENTRY *entry;

  /* Restore the original of this history line, iff the line that we
     are editing was originally in the history, AND the line has changed. */
  entry = current_history ();

  if (entry && rl_undo_list)
    {
      temp = savestring (the_line);
      rl_revert_line (1, 0);
      entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL);
      _rl_free_history_entry (entry);

      strcpy (the_line, temp);
      free (temp);
    }

  /* At any rate, it is highly likely that this line has an undo list.  Get
     rid of it now. */
  if (rl_undo_list)
    free_undo_list ();

  return (eof ? (char *)NULL : savestring (the_line));
}

STATIC_CALLBACK int
#if defined (READLINE_CALLBACKS)
readline_internal_char ()
#else
readline_internal_charloop ()
#endif
{
  static int lastc, eof_found;
  int c, code, lk;

  lastc = -1;
  eof_found = 0;

#if !defined (READLINE_CALLBACKS)
  while (rl_done == 0)
    {
#endif
      lk = _rl_last_command_was_kill;

      code = setjmp (readline_top_level);

      if (code)
	(*rl_redisplay_function) ();

      if (rl_pending_input == 0)
	{
	  /* Then initialize the argument and number of keys read. */
	  _rl_init_argument ();
	  rl_key_sequence_length = 0;
	}

      c = rl_read_key ();

      /* EOF typed to a non-blank line is a <NL>. */
      if (c == EOF && rl_end)
	c = NEWLINE;

      /* The character _rl_eof_char typed to blank line, and not as the
	 previous character is interpreted as EOF. */
      if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
	{
#if defined (READLINE_CALLBACKS)
	  return (rl_done = 1);
#else
	  eof_found = 1;
	  break;
#endif
	}

      lastc = c;
      _rl_dispatch ((unsigned char)c, _rl_keymap);

      /* If there was no change in _rl_last_command_was_kill, then no kill
	 has taken place.  Note that if input is pending we are reading
	 a prefix command, so nothing has changed yet. */
      if (rl_pending_input == 0 && lk == _rl_last_command_was_kill)
	_rl_last_command_was_kill = 0;

#if defined (VI_MODE)
      /* In vi mode, when you exit insert mode, the cursor moves back
	 over the previous character.  We explicitly check for that here. */
      if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
	rl_vi_check ();
#endif /* VI_MODE */

      if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read)
        {
          (*rl_redisplay_function) ();
          rl_newline (1, '\n');
        }

      if (rl_done == 0)
	(*rl_redisplay_function) ();

      /* If the application writer has told us to erase the entire line if
	  the only character typed was something bound to rl_newline, do so. */
      if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline &&
	  rl_point == 0 && rl_end == 0)
	_rl_erase_entire_line ();

#if defined (READLINE_CALLBACKS)
      return 0;
#else
    }

  return (eof_found);
#endif
}

#if defined (READLINE_CALLBACKS)
static int
readline_internal_charloop ()
{
  int eof = 1;

  while (rl_done == 0)
    eof = readline_internal_char ();
  return (eof);
}
#endif /* READLINE_CALLBACKS */

/* Read a line of input from the global rl_instream, doing output on
   the global rl_outstream.
   If rl_prompt is non-null, then that is our prompt. */
static char *
readline_internal ()
{
  int eof;

  readline_internal_setup ();
  eof = readline_internal_charloop ();
  return (readline_internal_teardown (eof));
}

void
_rl_init_line_state ()
{
  rl_point = rl_end = 0;
  the_line = rl_line_buffer;
  the_line[0] = 0;
}

void
_rl_set_the_line ()
{
  the_line = rl_line_buffer;
}

/* Do the command associated with KEY in MAP.
   If the associated command is really a keymap, then read
   another key, and dispatch into that map. */
int
_rl_dispatch (key, map)
     register int key;
     Keymap map;
{
  int r, newkey;
  char *macro;
  Function *func;

  if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
    {
      if (map[ESC].type == ISKMAP)
	{
	  if (_rl_defining_kbd_macro)
	    _rl_add_macro_char (ESC);
	  map = FUNCTION_TO_KEYMAP (map, ESC);
	  key = UNMETA (key);
	  rl_key_sequence_length += 2;
	  return (_rl_dispatch (key, map));
	}
      else
	ding ();
      return 0;
    }

  if (_rl_defining_kbd_macro)
    _rl_add_macro_char (key);

  r = 0;
  switch (map[key].type)
    {
    case ISFUNC:
      func = map[key].function;
      if (func != (Function *)NULL)
	{
	  /* Special case rl_do_lowercase_version (). */
	  if (func == rl_do_lowercase_version)

⌨️ 快捷键说明

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