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