File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / callback.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 01:01:01 2021 UTC (3 years, 3 months ago) by misho
Branches: readline, MAIN
CVS tags: v8_2p0, v8_1p0, HEAD
readline 8.1

    1: /* callback.c -- functions to use readline as an X `callback' mechanism. */
    2: 
    3: /* Copyright (C) 1987-2017 Free Software Foundation, Inc.
    4: 
    5:    This file is part of the GNU Readline Library (Readline), a library
    6:    for reading lines of text with interactive input and history editing.
    7: 
    8:    Readline is free software: you can redistribute it and/or modify
    9:    it under the terms of the GNU General Public License as published by
   10:    the Free Software Foundation, either version 3 of the License, or
   11:    (at your option) any later version.
   12: 
   13:    Readline is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:    GNU General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU General Public License
   19:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
   20: */
   21: 
   22: #define READLINE_LIBRARY
   23: 
   24: #if defined (HAVE_CONFIG_H)
   25: #  include <config.h>
   26: #endif
   27: 
   28: #include "rlconf.h"
   29: 
   30: #if defined (READLINE_CALLBACKS)
   31: 
   32: #include <sys/types.h>
   33: 
   34: #ifdef HAVE_STDLIB_H
   35: #  include <stdlib.h>
   36: #else
   37: #  include "ansi_stdlib.h"
   38: #endif
   39: 
   40: #include <stdio.h>
   41: 
   42: /* System-specific feature definitions and include files. */
   43: #include "rldefs.h"
   44: #include "readline.h"
   45: #include "rlprivate.h"
   46: #include "xmalloc.h"
   47: 
   48: /* Private data for callback registration functions.  See comments in
   49:    rl_callback_read_char for more details. */
   50: _rl_callback_func_t *_rl_callback_func = 0;
   51: _rl_callback_generic_arg *_rl_callback_data = 0;
   52: 
   53: /* Applications can set this to non-zero to have readline's signal handlers
   54:    installed during the entire duration of reading a complete line, as in
   55:    readline-6.2.  This should be used with care, because it can result in
   56:    readline receiving signals and not handling them until it's called again
   57:    via rl_callback_read_char, thereby stealing them from the application.
   58:    By default, signal handlers are only active while readline is active. */   
   59: int rl_persistent_signal_handlers = 0;
   60: 
   61: /* **************************************************************** */
   62: /*								    */
   63: /*			Callback Readline Functions		    */
   64: /*								    */
   65: /* **************************************************************** */
   66: 
   67: /* Allow using readline in situations where a program may have multiple
   68:    things to handle at once, and dispatches them via select().  Call
   69:    rl_callback_handler_install() with the prompt and a function to call
   70:    whenever a complete line of input is ready.  The user must then
   71:    call rl_callback_read_char() every time some input is available, and 
   72:    rl_callback_read_char() will call the user's function with the complete
   73:    text read in at each end of line.  The terminal is kept prepped
   74:    all the time, except during calls to the user's function.  Signal
   75:    handlers are only installed when the application calls back into
   76:    readline, so readline doesn't `steal' signals from the application.  */
   77: 
   78: rl_vcpfunc_t *rl_linefunc;		/* user callback function */
   79: static int in_handler;		/* terminal_prepped and signals set? */
   80: 
   81: /* Make sure the terminal is set up, initialize readline, and prompt. */
   82: static void
   83: _rl_callback_newline (void)
   84: {
   85:   rl_initialize ();
   86: 
   87:   if (in_handler == 0)
   88:     {
   89:       in_handler = 1;
   90: 
   91:       if (rl_prep_term_function)
   92: 	(*rl_prep_term_function) (_rl_meta_flag);
   93: 
   94: #if defined (HANDLE_SIGNALS)
   95:       if (rl_persistent_signal_handlers)
   96: 	rl_set_signals ();
   97: #endif
   98:     }
   99: 
  100:   readline_internal_setup ();
  101:   RL_CHECK_SIGNALS ();
  102: }
  103: 
  104: /* Install a readline handler, set up the terminal, and issue the prompt. */
  105: void
  106: rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *linefunc)
  107: {
  108:   rl_set_prompt (prompt);
  109:   RL_SETSTATE (RL_STATE_CALLBACK);
  110:   rl_linefunc = linefunc;
  111:   _rl_callback_newline ();
  112: }
  113: 
  114: #if defined (HANDLE_SIGNALS)
  115: #define CALLBACK_READ_RETURN() \
  116:   do { \
  117:     if (rl_persistent_signal_handlers == 0) \
  118:       rl_clear_signals (); \
  119:     return; \
  120:   } while (0)
  121: #else
  122: #define CALLBACK_READ_RETURN() return
  123: #endif
  124: 
  125: /* Read one character, and dispatch to the handler if it ends the line. */
  126: void
  127: rl_callback_read_char (void)
  128: {
  129:   char *line;
  130:   int eof, jcode;
  131:   static procenv_t olevel;
  132: 
  133:   if (rl_linefunc == NULL)
  134:     {
  135:       _rl_errmsg ("readline_callback_read_char() called with no handler!");
  136:       abort ();
  137:     }
  138: 
  139:   memcpy ((void *)olevel, (void *)_rl_top_level, sizeof (procenv_t));
  140: #if defined (HAVE_POSIX_SIGSETJMP)
  141:   jcode = sigsetjmp (_rl_top_level, 0);
  142: #else
  143:   jcode = setjmp (_rl_top_level);
  144: #endif
  145:   if (jcode)
  146:     {
  147:       (*rl_redisplay_function) ();
  148:       _rl_want_redisplay = 0;
  149:       memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
  150:       CALLBACK_READ_RETURN ();
  151:     }
  152: 
  153: #if defined (HANDLE_SIGNALS)
  154:   /* Install signal handlers only when readline has control. */
  155:   if (rl_persistent_signal_handlers == 0)
  156:     rl_set_signals ();
  157: #endif
  158: 
  159:   do
  160:     {
  161:       RL_CHECK_SIGNALS ();
  162:       if  (RL_ISSTATE (RL_STATE_ISEARCH))
  163: 	{
  164: 	  eof = _rl_isearch_callback (_rl_iscxt);
  165: 	  if (eof == 0 && (RL_ISSTATE (RL_STATE_ISEARCH) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
  166: 	    rl_callback_read_char ();
  167: 
  168: 	  CALLBACK_READ_RETURN ();
  169: 	}
  170:       else if  (RL_ISSTATE (RL_STATE_NSEARCH))
  171: 	{
  172: 	  eof = _rl_nsearch_callback (_rl_nscxt);
  173: 
  174: 	  CALLBACK_READ_RETURN ();
  175: 	}
  176: #if defined (VI_MODE)
  177:       /* States that can occur while in state VIMOTION have to be checked
  178: 	 before RL_STATE_VIMOTION */
  179:       else if (RL_ISSTATE (RL_STATE_CHARSEARCH))
  180: 	{
  181: 	  int k;
  182: 
  183: 	  k = _rl_callback_data->i2;
  184: 
  185: 	  eof = (*_rl_callback_func) (_rl_callback_data);
  186: 	  /* If the function `deregisters' itself, make sure the data is
  187: 	     cleaned up. */
  188: 	  if (_rl_callback_func == 0)	/* XXX - just sanity check */
  189: 	    {
  190: 	      if (_rl_callback_data)
  191: 		{
  192: 		  _rl_callback_data_dispose (_rl_callback_data);
  193: 		  _rl_callback_data = 0;
  194: 		}
  195: 	    }
  196: 
  197: 	  /* Messy case where vi motion command can be char search */
  198: 	  if (RL_ISSTATE (RL_STATE_VIMOTION))
  199: 	    {
  200: 	      _rl_vi_domove_motion_cleanup (k, _rl_vimvcxt);
  201: 	      _rl_internal_char_cleanup ();
  202: 	      CALLBACK_READ_RETURN ();	      
  203: 	    }
  204: 
  205: 	  _rl_internal_char_cleanup ();
  206: 	}
  207:       else if (RL_ISSTATE (RL_STATE_VIMOTION))
  208: 	{
  209: 	  eof = _rl_vi_domove_callback (_rl_vimvcxt);
  210: 	  /* Should handle everything, including cleanup, numeric arguments,
  211: 	     and turning off RL_STATE_VIMOTION */
  212: 	  if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
  213: 	    _rl_internal_char_cleanup ();
  214: 
  215: 	  CALLBACK_READ_RETURN ();
  216: 	}
  217: #endif
  218:       else if (RL_ISSTATE (RL_STATE_NUMERICARG))
  219: 	{
  220: 	  eof = _rl_arg_callback (_rl_argcxt);
  221: 	  if (eof == 0 && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
  222: 	    rl_callback_read_char ();
  223: 	  /* XXX - this should handle _rl_last_command_was_kill better */
  224: 	  else if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
  225: 	    _rl_internal_char_cleanup ();
  226: 
  227: 	  CALLBACK_READ_RETURN ();
  228: 	}
  229:       else if (RL_ISSTATE (RL_STATE_MULTIKEY))
  230: 	{
  231: 	  eof = _rl_dispatch_callback (_rl_kscxt);	/* For now */
  232: 	  while ((eof == -1 || eof == -2) && RL_ISSTATE (RL_STATE_MULTIKEY) && _rl_kscxt && (_rl_kscxt->flags & KSEQ_DISPATCHED))
  233: 	    eof = _rl_dispatch_callback (_rl_kscxt);
  234: 	  if (RL_ISSTATE (RL_STATE_MULTIKEY) == 0)
  235: 	    {
  236: 	      _rl_internal_char_cleanup ();
  237: 	      _rl_want_redisplay = 1;
  238: 	    }
  239: 	}
  240:       else if (_rl_callback_func)
  241: 	{
  242: 	  /* This allows functions that simply need to read an additional
  243: 	     character (like quoted-insert) to register a function to be
  244: 	     called when input is available.  _rl_callback_data is a
  245: 	     pointer to a struct that has the argument count originally
  246: 	     passed to the registering function and space for any additional
  247: 	     parameters.  */
  248: 	  eof = (*_rl_callback_func) (_rl_callback_data);
  249: 	  /* If the function `deregisters' itself, make sure the data is
  250: 	     cleaned up. */
  251: 	  if (_rl_callback_func == 0)
  252: 	    {
  253: 	      if (_rl_callback_data) 	
  254: 		{
  255: 		  _rl_callback_data_dispose (_rl_callback_data);
  256: 		  _rl_callback_data = 0;
  257: 		}
  258: 	      _rl_internal_char_cleanup ();
  259: 	    }
  260: 	}
  261:       else
  262: 	eof = readline_internal_char ();
  263: 
  264:       RL_CHECK_SIGNALS ();
  265:       if (rl_done == 0 && _rl_want_redisplay)
  266: 	{
  267: 	  (*rl_redisplay_function) ();
  268: 	  _rl_want_redisplay = 0;
  269: 	}
  270: 
  271:       if (rl_done)
  272: 	{
  273: 	  line = readline_internal_teardown (eof);
  274: 
  275: 	  if (rl_deprep_term_function)
  276: 	    (*rl_deprep_term_function) ();
  277: #if defined (HANDLE_SIGNALS)
  278: 	  rl_clear_signals ();
  279: #endif
  280: 	  in_handler = 0;
  281: 	  (*rl_linefunc) (line);
  282: 
  283: 	  /* If the user did not clear out the line, do it for him. */
  284: 	  if (rl_line_buffer[0])
  285: 	    _rl_init_line_state ();
  286: 
  287: 	  /* Redisplay the prompt if readline_handler_{install,remove}
  288: 	     not called. */
  289: 	  if (in_handler == 0 && rl_linefunc)
  290: 	    _rl_callback_newline ();
  291: 	}
  292:     }
  293:   while (rl_pending_input || _rl_pushed_input_available () || RL_ISSTATE (RL_STATE_MACROINPUT));
  294: 
  295:   CALLBACK_READ_RETURN ();
  296: }
  297: 
  298: /* Remove the handler, and make sure the terminal is in its normal state. */
  299: void
  300: rl_callback_handler_remove (void)
  301: {
  302:   rl_linefunc = NULL;
  303:   RL_UNSETSTATE (RL_STATE_CALLBACK);
  304:   RL_CHECK_SIGNALS ();
  305:   if (in_handler)
  306:     {
  307:       in_handler = 0;
  308:       if (rl_deprep_term_function)
  309: 	(*rl_deprep_term_function) ();
  310: #if defined (HANDLE_SIGNALS)
  311:       rl_clear_signals ();
  312: #endif
  313:     }
  314: }
  315: 
  316: _rl_callback_generic_arg *
  317: _rl_callback_data_alloc (int count)
  318: {
  319:   _rl_callback_generic_arg *arg;
  320: 
  321:   arg = (_rl_callback_generic_arg *)xmalloc (sizeof (_rl_callback_generic_arg));
  322:   arg->count = count;
  323: 
  324:   arg->i1 = arg->i2 = 0;
  325: 
  326:   return arg;
  327: }
  328: 
  329: void
  330: _rl_callback_data_dispose (_rl_callback_generic_arg *arg)
  331: {
  332:   xfree (arg);
  333: }
  334: 
  335: /* Make sure that this agrees with cases in rl_callback_read_char */
  336: void
  337: rl_callback_sigcleanup (void)
  338: {
  339:   if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
  340:     return;
  341: 
  342:   if (RL_ISSTATE (RL_STATE_ISEARCH))
  343:     _rl_isearch_cleanup (_rl_iscxt, 0);
  344:   else if (RL_ISSTATE (RL_STATE_NSEARCH))
  345:     _rl_nsearch_cleanup (_rl_nscxt, 0);
  346:   else if (RL_ISSTATE (RL_STATE_VIMOTION))
  347:     RL_UNSETSTATE (RL_STATE_VIMOTION);
  348:   else if (RL_ISSTATE (RL_STATE_NUMERICARG))
  349:     {
  350:       _rl_argcxt = 0;
  351:       RL_UNSETSTATE (RL_STATE_NUMERICARG);
  352:     }
  353:   else if (RL_ISSTATE (RL_STATE_MULTIKEY))
  354:     RL_UNSETSTATE (RL_STATE_MULTIKEY);
  355:   if (RL_ISSTATE (RL_STATE_CHARSEARCH))
  356:     RL_UNSETSTATE (RL_STATE_CHARSEARCH);
  357: 
  358:   _rl_callback_func = 0;
  359: }
  360: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>