xref: /netbsd-src/external/gpl3/gdb/dist/readline/readline/callback.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
1 /* callback.c -- functions to use readline as an X `callback' mechanism. */
2 
3 /* Copyright (C) 1987-2022 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
_rl_callback_newline(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
rl_callback_handler_install(const char * prompt,rl_vcpfunc_t * linefunc)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
rl_callback_read_char(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   eof = 0;
140 
141   memcpy ((void *)olevel, (void *)_rl_top_level, sizeof (procenv_t));
142 #if defined (HAVE_POSIX_SIGSETJMP)
143   jcode = sigsetjmp (_rl_top_level, 0);
144 #else
145   jcode = setjmp (_rl_top_level);
146 #endif
147   if (jcode)
148     {
149       (*rl_redisplay_function) ();
150       _rl_want_redisplay = 0;
151       memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
152       CALLBACK_READ_RETURN ();
153     }
154 
155 #if defined (HANDLE_SIGNALS)
156   /* Install signal handlers only when readline has control. */
157   if (rl_persistent_signal_handlers == 0)
158     rl_set_signals ();
159 #endif
160 
161   do
162     {
163       RL_CHECK_SIGNALS ();
164       if  (RL_ISSTATE (RL_STATE_ISEARCH))
165 	{
166 	  eof = _rl_isearch_callback (_rl_iscxt);
167 	  if (eof == 0 && (RL_ISSTATE (RL_STATE_ISEARCH) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
168 	    rl_callback_read_char ();
169 
170 	  CALLBACK_READ_RETURN ();
171 	}
172       else if  (RL_ISSTATE (RL_STATE_NSEARCH))
173 	{
174 	  eof = _rl_nsearch_callback (_rl_nscxt);
175 
176 	  CALLBACK_READ_RETURN ();
177 	}
178 #if defined (VI_MODE)
179       /* States that can occur while in state VIMOTION have to be checked
180 	 before RL_STATE_VIMOTION */
181       else if (RL_ISSTATE (RL_STATE_CHARSEARCH))
182 	{
183 	  int k;
184 
185 	  k = _rl_callback_data->i2;
186 
187 	  eof = (*_rl_callback_func) (_rl_callback_data);
188 	  /* If the function `deregisters' itself, make sure the data is
189 	     cleaned up. */
190 	  if (_rl_callback_func == 0)	/* XXX - just sanity check */
191 	    {
192 	      if (_rl_callback_data)
193 		{
194 		  _rl_callback_data_dispose (_rl_callback_data);
195 		  _rl_callback_data = 0;
196 		}
197 	    }
198 
199 	  /* Messy case where vi motion command can be char search */
200 	  if (RL_ISSTATE (RL_STATE_VIMOTION))
201 	    {
202 	      _rl_vi_domove_motion_cleanup (k, _rl_vimvcxt);
203 	      _rl_internal_char_cleanup ();
204 	      CALLBACK_READ_RETURN ();
205 	    }
206 
207 	  _rl_internal_char_cleanup ();
208 	}
209       else if (RL_ISSTATE (RL_STATE_VIMOTION))
210 	{
211 	  eof = _rl_vi_domove_callback (_rl_vimvcxt);
212 	  /* Should handle everything, including cleanup, numeric arguments,
213 	     and turning off RL_STATE_VIMOTION */
214 	  if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
215 	    _rl_internal_char_cleanup ();
216 
217 	  CALLBACK_READ_RETURN ();
218 	}
219 #endif
220       else if (RL_ISSTATE (RL_STATE_NUMERICARG))
221 	{
222 	  eof = _rl_arg_callback (_rl_argcxt);
223 	  if (eof == 0 && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
224 	    rl_callback_read_char ();
225 	  /* XXX - this should handle _rl_last_command_was_kill better */
226 	  else if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
227 	    _rl_internal_char_cleanup ();
228 
229 	  CALLBACK_READ_RETURN ();
230 	}
231       else if (RL_ISSTATE (RL_STATE_MULTIKEY))
232 	{
233 	  eof = _rl_dispatch_callback (_rl_kscxt);	/* For now */
234 	  while ((eof == -1 || eof == -2) && RL_ISSTATE (RL_STATE_MULTIKEY) && _rl_kscxt && (_rl_kscxt->flags & KSEQ_DISPATCHED))
235 	    eof = _rl_dispatch_callback (_rl_kscxt);
236 	  if (RL_ISSTATE (RL_STATE_MULTIKEY) == 0)
237 	    {
238 	      _rl_internal_char_cleanup ();
239 	      _rl_want_redisplay = 1;
240 	    }
241 	}
242       else if (_rl_callback_func)
243 	{
244 	  /* This allows functions that simply need to read an additional
245 	     character (like quoted-insert) to register a function to be
246 	     called when input is available.  _rl_callback_data is a
247 	     pointer to a struct that has the argument count originally
248 	     passed to the registering function and space for any additional
249 	     parameters.  */
250 	  eof = (*_rl_callback_func) (_rl_callback_data);
251 	  /* If the function `deregisters' itself, make sure the data is
252 	     cleaned up. */
253 	  if (_rl_callback_func == 0)
254 	    {
255 	      if (_rl_callback_data)
256 		{
257 		  _rl_callback_data_dispose (_rl_callback_data);
258 		  _rl_callback_data = 0;
259 		}
260 	      _rl_internal_char_cleanup ();
261 	    }
262 	}
263       else
264 	eof = readline_internal_char ();
265 
266       RL_CHECK_SIGNALS ();
267       if (rl_done == 0 && _rl_want_redisplay)
268 	{
269 	  (*rl_redisplay_function) ();
270 	  _rl_want_redisplay = 0;
271 	}
272 
273       /* Make sure application hooks can see whether we saw EOF. */
274       if (eof > 0)
275 	{
276 	  rl_eof_found = eof;
277 	  RL_SETSTATE(RL_STATE_EOF);
278 	}
279 
280       if (rl_done)
281 	{
282 	  line = readline_internal_teardown (eof);
283 
284 	  if (rl_deprep_term_function)
285 	    (*rl_deprep_term_function) ();
286 #if defined (HANDLE_SIGNALS)
287 	  rl_clear_signals ();
288 #endif
289 	  in_handler = 0;
290 	  (*rl_linefunc) (line);
291 
292 	  /* If the user did not clear out the line, do it for him. */
293 	  if (rl_line_buffer[0])
294 	    _rl_init_line_state ();
295 
296 	  /* Redisplay the prompt if readline_handler_{install,remove}
297 	     not called. */
298 	  if (in_handler == 0 && rl_linefunc)
299 	    _rl_callback_newline ();
300 	}
301     }
302   while (rl_pending_input || _rl_pushed_input_available () || RL_ISSTATE (RL_STATE_MACROINPUT));
303 
304   CALLBACK_READ_RETURN ();
305 }
306 
307 /* Remove the handler, and make sure the terminal is in its normal state. */
308 void
rl_callback_handler_remove(void)309 rl_callback_handler_remove (void)
310 {
311   rl_linefunc = NULL;
312   RL_UNSETSTATE (RL_STATE_CALLBACK);
313   RL_CHECK_SIGNALS ();
314   if (in_handler)
315     {
316       in_handler = 0;
317       if (rl_deprep_term_function)
318 	(*rl_deprep_term_function) ();
319 #if defined (HANDLE_SIGNALS)
320       rl_clear_signals ();
321 #endif
322     }
323 }
324 
325 _rl_callback_generic_arg *
_rl_callback_data_alloc(int count)326 _rl_callback_data_alloc (int count)
327 {
328   _rl_callback_generic_arg *arg;
329 
330   arg = (_rl_callback_generic_arg *)xmalloc (sizeof (_rl_callback_generic_arg));
331   arg->count = count;
332 
333   arg->i1 = arg->i2 = 0;
334 
335   return arg;
336 }
337 
338 void
_rl_callback_data_dispose(_rl_callback_generic_arg * arg)339 _rl_callback_data_dispose (_rl_callback_generic_arg *arg)
340 {
341   xfree (arg);
342 }
343 
344 /* Make sure that this agrees with cases in rl_callback_read_char */
345 void
rl_callback_sigcleanup(void)346 rl_callback_sigcleanup (void)
347 {
348   if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
349     return;
350 
351   if (RL_ISSTATE (RL_STATE_ISEARCH))
352     _rl_isearch_cleanup (_rl_iscxt, 0);
353   else if (RL_ISSTATE (RL_STATE_NSEARCH))
354     _rl_nsearch_cleanup (_rl_nscxt, 0);
355   else if (RL_ISSTATE (RL_STATE_VIMOTION))
356     RL_UNSETSTATE (RL_STATE_VIMOTION);
357   else if (RL_ISSTATE (RL_STATE_NUMERICARG))
358     {
359       _rl_argcxt = 0;
360       RL_UNSETSTATE (RL_STATE_NUMERICARG);
361     }
362   else if (RL_ISSTATE (RL_STATE_MULTIKEY))
363     RL_UNSETSTATE (RL_STATE_MULTIKEY);
364   if (RL_ISSTATE (RL_STATE_CHARSEARCH))
365     RL_UNSETSTATE (RL_STATE_CHARSEARCH);
366 
367   _rl_callback_func = 0;
368 }
369 #endif
370