* tuiWin.c, tui.c, tuiCommand.c: Use ansi prototype.
[deliverable/binutils-gdb.git] / gdb / tui / tui.c
1 /* General functions for the WDB TUI.
2 Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3 Contributed by Hewlett-Packard Company.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include <malloc.h>
26 #ifdef HAVE_TERM_H
27 #include <term.h>
28 #endif
29 #include <signal.h>
30 #include <fcntl.h>
31 #include <termio.h>
32 #include <setjmp.h>
33 #include "defs.h"
34 #include "gdbcmd.h"
35 #include "tui.h"
36 #include "tuiData.h"
37 #include "tuiLayout.h"
38 #include "tuiIO.h"
39 #include "tuiRegs.h"
40 #include "tuiWin.h"
41
42 /* The Solaris header files seem to provide no declaration for this at
43 all when __STDC__ is defined. This shouldn't conflict with
44 anything. */
45 extern char *tgoto ();
46
47 /***********************
48 ** Local Definitions
49 ************************/
50 #define FILEDES 2
51 /* Solaris <sys/termios.h> defines CTRL. */
52 #ifndef CTRL
53 #define CTRL(x) (x & ~0140)
54 #endif
55 #define CHK(val, dft) (val<=0 ? dft : val)
56
57 #define TOGGLE_USAGE "Usage:toggle breakpoints"
58 #define TUI_TOGGLE_USAGE "Usage:\ttoggle $fregs\n\ttoggle breakpoints"
59
60 /*****************************
61 ** Local static forward decls
62 ******************************/
63 static void _tuiReset (void);
64 static void _toggle_command (char *, int);
65 static void _tui_vToggle_command (va_list);
66 static Opaque _tui_vDo (TuiOpaqueFuncPtr, va_list);
67
68
69
70 /***********************
71 ** Public Functions
72 ************************/
73
74 /*
75 ** tuiInit().
76 */
77 void
78 tuiInit (char *argv0)
79 {
80 extern void init_page_info ();
81 extern void initialize_tui_files (void);
82
83 initialize_tui_files ();
84 initializeStaticData ();
85 initscr ();
86 refresh ();
87 setTermHeightTo (LINES);
88 setTermWidthTo (COLS);
89 tuiInitWindows ();
90 wrefresh (cmdWin->generic.handle);
91 init_page_info ();
92 /* Don't hook debugger output if doing command-window
93 * the XDB way. However, one thing we do want to do in
94 * XDB style is set up the scrolling region to be
95 * the bottom of the screen (tuiTermUnsetup()).
96 */
97 fputs_unfiltered_hook = NULL;
98 rl_initialize (); /* need readline initialization to
99 * create termcap sequences
100 */
101 tuiTermUnsetup (1, cmdWin->detail.commandInfo.curch);
102
103 return;
104 } /* tuiInit */
105
106
107 /*
108 ** tuiInitWindows().
109 */
110 void
111 tuiInitWindows (void)
112 {
113 TuiWinType type;
114
115 tuiSetLocatorContent (0);
116 showLayout (SRC_COMMAND);
117 keypad (cmdWin->generic.handle, TRUE);
118 echo ();
119 crmode ();
120 nl ();
121 tuiSetWinFocusTo (srcWin);
122
123 return;
124 } /* tuiInitWindows */
125
126
127 /*
128 ** tuiCleanUp().
129 ** Kill signal handler and cleanup termination method
130 */
131 void
132 tuiResetScreen (void)
133 {
134 TuiWinType type = SRC_WIN;
135
136 keypad (cmdWin->generic.handle, FALSE);
137 for (; type < MAX_MAJOR_WINDOWS; type++)
138 {
139 if (m_winPtrNotNull (winList[type]) &&
140 winList[type]->generic.type != UNDEFINED_WIN &&
141 !winList[type]->generic.isVisible)
142 tuiDelWindow (winList[type]);
143 }
144 endwin ();
145 initscr ();
146 refresh ();
147 echo ();
148 crmode ();
149 nl ();
150
151 return;
152 } /* tuiResetScreen */
153
154
155 /*
156 ** tuiCleanUp().
157 ** Kill signal handler and cleanup termination method
158 */
159 void
160 tuiCleanUp (void)
161 {
162 char *buffer;
163 extern char *term_cursor_move;
164
165 signal (SIGINT, SIG_IGN);
166 tuiTermSetup (0); /* Restore scrolling region to whole screen */
167 keypad (cmdWin->generic.handle, FALSE);
168 freeAllWindows ();
169 endwin ();
170 buffer = tgoto (term_cursor_move, 0, termHeight ());
171 tputs (buffer, 1, putchar);
172 _tuiReset ();
173
174 return;
175 } /* tuiCleanUp */
176
177
178 /*
179 ** tuiError().
180 */
181 void
182 tuiError (char *string, int exitGdb)
183 {
184 puts_unfiltered (string);
185 if (exitGdb)
186 {
187 tuiCleanUp ();
188 exit (-1);
189 }
190
191 return;
192 } /* tuiError */
193
194
195 /*
196 ** tui_vError()
197 ** tuiError with args in a va_list.
198 */
199 void
200 tui_vError (va_list args)
201 {
202 char *string;
203 int exitGdb;
204
205 string = va_arg (args, char *);
206 exitGdb = va_arg (args, int);
207
208 tuiError (string, exitGdb);
209
210 return;
211 } /* tui_vError */
212
213
214 /*
215 ** tuiFree()
216 ** Wrapper on top of free() to ensure that input address is greater than 0x0
217 */
218 void
219 tuiFree (char *ptr)
220 {
221 if (ptr != (char *) NULL)
222 {
223 xfree (ptr);
224 }
225
226 return;
227 } /* tuiFree */
228
229
230 /* tuiGetLowDisassemblyAddress().
231 ** Determine what the low address will be to display in the TUI's
232 ** disassembly window. This may or may not be the same as the
233 ** low address input.
234 */
235 Opaque
236 tuiGetLowDisassemblyAddress (Opaque low, Opaque pc)
237 {
238 int line;
239 Opaque newLow;
240
241 /*
242 ** Determine where to start the disassembly so that the pc is about in the
243 ** middle of the viewport.
244 */
245 for (line = 0, newLow = pc;
246 (newLow > low &&
247 line < (tuiDefaultWinViewportHeight (DISASSEM_WIN,
248 DISASSEM_COMMAND) / 2));)
249 {
250 bfd_byte buffer[4];
251
252 newLow -= sizeof (bfd_getb32 (buffer));
253 line++;
254 }
255
256 return newLow;
257 } /* tuiGetLowDisassemblyAddress */
258
259
260 /* tui_vGetLowDisassemblyAddress().
261 ** Determine what the low address will be to display in the TUI's
262 ** disassembly window with args in a va_list.
263 */
264 Opaque
265 tui_vGetLowDisassemblyAddress (va_list args)
266 {
267 int line;
268 Opaque newLow;
269 Opaque low;
270 Opaque pc;
271
272 low = va_arg (args, Opaque);
273 pc = va_arg (args, Opaque);
274
275 return (tuiGetLowDisassemblyAddress (low, pc));
276
277 } /* tui_vGetLowDisassemblyAddress */
278
279
280 /*
281 ** tuiDo().
282 ** General purpose function to execute a tui function. Transitions
283 ** between curses and the are handled here. This function is called
284 ** by non-tui gdb functions.
285 **
286 ** Errors are caught here.
287 ** If there is no error, the value returned by 'func' is returned.
288 ** If there is an error, then zero is returned.
289 **
290 ** Must not be called with immediate_quit in effect (bad things might
291 ** happen, say we got a signal in the middle of a memcpy to quit_return).
292 ** This is an OK restriction; with very few exceptions immediate_quit can
293 ** be replaced by judicious use of QUIT.
294 */
295 Opaque
296 tuiDo (TuiOpaqueFuncPtr func, ...)
297 {
298 extern int terminal_is_ours;
299
300 Opaque ret = (Opaque) NULL;
301
302 /* It is an error to be tuiDo'ing if we
303 * don't own the terminal.
304 */
305 if (!terminal_is_ours)
306 return ret;
307
308 if (tui_version)
309 {
310 va_list args;
311
312 va_start (args, func);
313 ret = _tui_vDo (func, args);
314 va_end (args);
315 }
316
317 return ret;
318 } /* tuiDo */
319
320
321 /*
322 ** tuiDoAndReturnToTop().
323 ** General purpose function to execute a tui function. Transitions
324 ** between curses and the are handled here. This function is called
325 ** by non-tui gdb functions who wish to reset gdb to the top level.
326 ** After the tuiDo is performed, a return to the top level occurs.
327 **
328 ** Errors are caught here.
329 ** If there is no error, the value returned by 'func' is returned.
330 ** If there is an error, then zero is returned.
331 **
332 ** Must not be called with immediate_quit in effect (bad things might
333 ** happen, say we got a signal in the middle of a memcpy to quit_return).
334 ** This is an OK restriction; with very few exceptions immediate_quit can
335 ** be replaced by judicious use of QUIT.
336 **
337 */
338 Opaque
339 tuiDoAndReturnToTop (TuiOpaqueFuncPtr func, ...)
340 {
341 extern int terminal_is_ours;
342
343 Opaque ret = (Opaque) NULL;
344
345 /* It is an error to be tuiDo'ing if we
346 * don't own the terminal.
347 */
348 if (!terminal_is_ours)
349 return ret;
350
351 if (tui_version)
352 {
353 va_list args;
354
355 va_start (args, func);
356 ret = _tui_vDo (func, args);
357
358 /* force a return to the top level */
359 return_to_top_level (RETURN_ERROR);
360 }
361
362 return ret;
363 } /* tuiDoAndReturnToTop */
364
365
366 void
367 tui_vSelectSourceSymtab (va_list args)
368 {
369 struct symtab *s = va_arg (args, struct symtab *);
370
371 select_source_symtab (s);
372 return;
373 } /* tui_vSelectSourceSymtab */
374
375
376 /*
377 ** _initialize_tui().
378 ** Function to initialize gdb commands, for tui window manipulation.
379 */
380 void
381 _initialize_tui (void)
382 {
383 #if 0
384 if (tui_version)
385 {
386 add_com ("toggle", class_tui, _toggle_command,
387 "Toggle Terminal UI Features\n\
388 Usage: Toggle $fregs\n\
389 \tToggles between single and double precision floating point registers.\n");
390 }
391 #endif
392 char *helpStr;
393
394 if (tui_version)
395 helpStr = "Toggle Specified Features\n\
396 Usage:\ttoggle $fregs\n\ttoggle breakpoints";
397 else
398 helpStr = "Toggle Specified Features\nUsage:toggle breakpoints";
399 add_abbrev_prefix_cmd ("toggle",
400 class_tui,
401 _toggle_command,
402 helpStr,
403 &togglelist,
404 "toggle ",
405 1,
406 &cmdlist);
407 } /* _initialize_tui */
408
409
410 /*
411 ** va_catch_errors().
412 ** General purpose function to execute a function, catching errors.
413 ** If there is no error, the value returned by 'func' is returned.
414 ** If there is error, then zero is returned.
415 ** Note that 'func' must take a variable argument list as well.
416 **
417 ** Must not be called with immediate_quit in effect (bad things might
418 ** happen, say we got a signal in the middle of a memcpy to quit_return).
419 ** This is an OK restriction; with very few exceptions immediate_quit can
420 ** be replaced by judicious use of QUIT.
421 */
422 Opaque
423 va_catch_errors (TuiOpaqueFuncPtr func, va_list args)
424 {
425 Opaque ret = (Opaque) NULL;
426
427 /*
428 ** We could have used catch_errors(), but it doesn't handle variable args.
429 ** Also, for the tui, we always want to catch all errors, so we don't
430 ** need to pass a mask, or an error string.
431 */
432 jmp_buf saved_error;
433 jmp_buf saved_quit;
434 jmp_buf tmp_jmp;
435 struct cleanup *saved_cleanup_chain;
436 char *saved_error_pre_print;
437 char *saved_quit_pre_print;
438 extern jmp_buf error_return;
439 extern jmp_buf quit_return;
440
441 saved_cleanup_chain = save_cleanups ();
442 saved_error_pre_print = error_pre_print;
443 saved_quit_pre_print = quit_pre_print;
444
445 memcpy ((char *) saved_error, (char *) error_return, sizeof (jmp_buf));
446 error_pre_print = "";
447 memcpy (saved_quit, quit_return, sizeof (jmp_buf));
448 quit_pre_print = "";
449
450 if (setjmp (tmp_jmp) == 0)
451 {
452 va_list argList = args;
453 memcpy (error_return, tmp_jmp, sizeof (jmp_buf));
454 memcpy (quit_return, tmp_jmp, sizeof (jmp_buf));
455 ret = func (argList);
456 }
457 restore_cleanups (saved_cleanup_chain);
458 memcpy (error_return, saved_error, sizeof (jmp_buf));
459 error_pre_print = saved_error_pre_print;
460 memcpy (quit_return, saved_quit, sizeof (jmp_buf));
461 quit_pre_print = saved_quit_pre_print;
462
463 return ret;
464 }
465
466 /*
467 ** vcatch_errors().
468 ** Catch errors occurring in tui or non tui function, handling
469 ** variable param lists. Note that 'func' must take a variable
470 ** argument list as well.
471 */
472 Opaque
473 vcatch_errors (OpaqueFuncPtr func, ...)
474 {
475 Opaque ret = (Opaque) NULL;
476 va_list args;
477 va_start (args, func);
478 /*
479 va_arg(args, OpaqueFuncPtr);
480 */
481 ret = va_catch_errors (func, args);
482 va_end (args);
483
484 return ret;
485 }
486
487
488 void
489 strcat_to_buf (char *buf, int buflen, char *itemToAdd)
490 {
491 if (itemToAdd != (char *) NULL && buf != (char *) NULL)
492 {
493 if ((strlen (buf) + strlen (itemToAdd)) <= buflen)
494 strcat (buf, itemToAdd);
495 else
496 strncat (buf, itemToAdd, (buflen - strlen (buf)));
497 }
498
499 return;
500 } /* strcat_to_buf */
501
502 /* VARARGS */
503 void
504 strcat_to_buf_with_fmt (char *buf, int bufLen, char *format, ...)
505 {
506 char *linebuffer;
507 struct cleanup *old_cleanups;
508 va_list args;
509 va_start (args, format);
510 vasprintf (&linebuffer, format, args);
511 old_cleanups = make_cleanup (xfree, linebuffer);
512 strcat_to_buf (buf, bufLen, linebuffer);
513 do_cleanups (old_cleanups);
514 va_end (args);
515 }
516
517
518
519
520
521 /***********************
522 ** Static Functions
523 ************************/
524
525
526 /*
527 ** _tui_vDo().
528 ** General purpose function to execute a tui function. Transitions
529 ** between curses and the are handled here. This function is called
530 ** by non-tui gdb functions.
531 **
532 ** Errors are caught here.
533 ** If there is no error, the value returned by 'func' is returned.
534 ** If there is an error, then zero is returned.
535 **
536 ** Must not be called with immediate_quit in effect (bad things might
537 ** happen, say we got a signal in the middle of a memcpy to quit_return).
538 ** This is an OK restriction; with very few exceptions immediate_quit can
539 ** be replaced by judicious use of QUIT.
540 */
541 static Opaque
542 _tui_vDo (TuiOpaqueFuncPtr func, va_list args)
543 {
544 extern int terminal_is_ours;
545
546 Opaque ret = (Opaque) NULL;
547
548 /* It is an error to be tuiDo'ing if we
549 * don't own the terminal.
550 */
551 if (!terminal_is_ours)
552 return ret;
553
554 if (tui_version)
555 {
556 /* If doing command window the "XDB way" (command window
557 * is unmanaged by curses...
558 */
559 /* Set up terminal for TUI */
560 tuiTermSetup (1);
561
562 ret = va_catch_errors (func, args);
563
564 /* Set up terminal for command window */
565 tuiTermUnsetup (1, cmdWin->detail.commandInfo.curch);
566 }
567
568 return ret;
569 } /* _tui_vDo */
570
571
572 static void
573 _toggle_command (char *arg, int fromTTY)
574 {
575 printf_filtered ("Specify feature to toggle.\n%s\n",
576 (tui_version) ? TUI_TOGGLE_USAGE : TOGGLE_USAGE);
577 /*
578 tuiDo((TuiOpaqueFuncPtr)_Toggle_command, arg, fromTTY);
579 */
580 }
581
582 /*
583 ** _tui_vToggle_command().
584 */
585 static void
586 _tui_vToggle_command (va_list args)
587 {
588 char *arg;
589 int fromTTY;
590
591 arg = va_arg (args, char *);
592
593 if (arg == (char *) NULL)
594 printf_filtered (TOGGLE_USAGE);
595 else
596 {
597 char *ptr = (char *) tuiStrDup (arg);
598 int i;
599
600 for (i = 0; (ptr[i]); i++)
601 ptr[i] = toupper (arg[i]);
602
603 if (subsetCompare (ptr, TUI_FLOAT_REGS_NAME))
604 tuiToggleFloatRegs ();
605 /* else if (subsetCompare(ptr, "ANOTHER TOGGLE OPTION"))
606 ...
607 */
608 else
609 printf_filtered (TOGGLE_USAGE);
610 tuiFree (ptr);
611 }
612
613 return;
614 } /* _tuiToggle_command */
615
616
617 static void
618 _tuiReset (void)
619 {
620 struct termio mode;
621
622 /*
623 ** reset the teletype mode bits to a sensible state.
624 ** Copied tset.c
625 */
626 #if ! defined (USG) && defined (TIOCGETC)
627 struct tchars tbuf;
628 #endif /* !USG && TIOCGETC */
629 #ifdef UCB_NTTY
630 struct ltchars ltc;
631
632 if (ldisc == NTTYDISC)
633 {
634 ioctl (FILEDES, TIOCGLTC, &ltc);
635 ltc.t_suspc = CHK (ltc.t_suspc, CTRL ('Z'));
636 ltc.t_dsuspc = CHK (ltc.t_dsuspc, CTRL ('Y'));
637 ltc.t_rprntc = CHK (ltc.t_rprntc, CTRL ('R'));
638 ltc.t_flushc = CHK (ltc.t_flushc, CTRL ('O'));
639 ltc.t_werasc = CHK (ltc.t_werasc, CTRL ('W'));
640 ltc.t_lnextc = CHK (ltc.t_lnextc, CTRL ('V'));
641 ioctl (FILEDES, TIOCSLTC, &ltc);
642 }
643 #endif /* UCB_NTTY */
644 #ifndef USG
645 #ifdef TIOCGETC
646 ioctl (FILEDES, TIOCGETC, &tbuf);
647 tbuf.t_intrc = CHK (tbuf.t_intrc, CTRL ('?'));
648 tbuf.t_quitc = CHK (tbuf.t_quitc, CTRL ('\\'));
649 tbuf.t_startc = CHK (tbuf.t_startc, CTRL ('Q'));
650 tbuf.t_stopc = CHK (tbuf.t_stopc, CTRL ('S'));
651 tbuf.t_eofc = CHK (tbuf.t_eofc, CTRL ('D'));
652 /* brkc is left alone */
653 ioctl (FILEDES, TIOCSETC, &tbuf);
654 #endif /* TIOCGETC */
655 mode.sg_flags &= ~(RAW
656 #ifdef CBREAK
657 | CBREAK
658 #endif /* CBREAK */
659 | VTDELAY | ALLDELAY);
660 mode.sg_flags |= XTABS | ECHO | CRMOD | ANYP;
661 #else /*USG */
662 ioctl (FILEDES, TCGETA, &mode);
663 mode.c_cc[VINTR] = CHK (mode.c_cc[VINTR], CTRL ('?'));
664 mode.c_cc[VQUIT] = CHK (mode.c_cc[VQUIT], CTRL ('\\'));
665 mode.c_cc[VEOF] = CHK (mode.c_cc[VEOF], CTRL ('D'));
666
667 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | INLCR | IGNCR | IUCLC | IXOFF);
668 mode.c_iflag |= (BRKINT | ISTRIP | ICRNL | IXON);
669 mode.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |
670 NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
671 mode.c_oflag |= (OPOST | ONLCR);
672 mode.c_cflag &= ~(CSIZE | PARODD | CLOCAL);
673 #ifndef hp9000s800
674 mode.c_cflag |= (CS8 | CREAD);
675 #else /*hp9000s800 */
676 mode.c_cflag |= (CS8 | CSTOPB | CREAD);
677 #endif /* hp9000s800 */
678 mode.c_lflag &= ~(XCASE | ECHONL | NOFLSH);
679 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOK);
680 ioctl (FILEDES, TCSETAW, &mode);
681 #endif /* USG */
682
683 return;
684 } /* _tuiReset */
This page took 0.042376 seconds and 4 git commands to generate.