2002-09-29 Elena Zannoni <ezannoni@redhat.com>
[deliverable/binutils-gdb.git] / gdb / tui / tuiSourceWin.c
1 /* TUI display source/assembly window.
2
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4 Inc.
5
6 Contributed by Hewlett-Packard Company.
7
8 This file is part of GDB.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
24
25 /* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
26 "defs.h" should be included first. Unfortunatly some systems
27 (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
28 and they clash with "bfd.h"'s definiton of true/false. The correct
29 fix is to remove true/false from "bfd.h", however, until that
30 happens, hack around it by including "config.h" and <curses.h>
31 first. */
32
33 #include "config.h"
34 #ifdef HAVE_NCURSES_H
35 #include <ncurses.h>
36 #else
37 #ifdef HAVE_CURSES_H
38 #include <curses.h>
39 #endif
40 #endif
41
42 #include "defs.h"
43 #include <ctype.h>
44 #include "symtab.h"
45 #include "frame.h"
46 #include "breakpoint.h"
47 #include "value.h"
48 #include "source.h"
49
50 #include "tui.h"
51 #include "tuiData.h"
52 #include "tuiStack.h"
53 #include "tuiWin.h"
54 #include "tuiGeneralWin.h"
55 #include "tuiSourceWin.h"
56 #include "tuiSource.h"
57 #include "tuiDisassem.h"
58
59
60 /* Function to display the "main" routine. */
61 void
62 tui_display_main (void)
63 {
64 if ((sourceWindows ())->count > 0)
65 {
66 CORE_ADDR addr;
67
68 addr = tuiGetBeginAsmAddress ();
69 if (addr != (CORE_ADDR) 0)
70 {
71 struct symtab_and_line sal;
72
73 tuiUpdateSourceWindowsWithAddr (addr);
74 sal = find_pc_line (addr, 0);
75 if (sal.symtab)
76 tuiUpdateLocatorFilename (sal.symtab->filename);
77 else
78 tuiUpdateLocatorFilename ("??");
79 }
80 }
81 }
82
83
84
85 /*
86 ** tuiUpdateSourceWindow().
87 ** Function to display source in the source window. This function
88 ** initializes the horizontal scroll to 0.
89 */
90 void
91 tuiUpdateSourceWindow (TuiWinInfoPtr winInfo, struct symtab *s,
92 TuiLineOrAddress lineOrAddr, int noerror)
93 {
94 winInfo->detail.sourceInfo.horizontalOffset = 0;
95 tuiUpdateSourceWindowAsIs (winInfo, s, lineOrAddr, noerror);
96
97 return;
98 } /* tuiUpdateSourceWindow */
99
100
101 /*
102 ** tuiUpdateSourceWindowAsIs().
103 ** Function to display source in the source/asm window. This
104 ** function shows the source as specified by the horizontal offset.
105 */
106 void
107 tuiUpdateSourceWindowAsIs (TuiWinInfoPtr winInfo, struct symtab *s,
108 TuiLineOrAddress lineOrAddr, int noerror)
109 {
110 TuiStatus ret;
111
112 if (winInfo->generic.type == SRC_WIN)
113 ret = tuiSetSourceContent (s, lineOrAddr.lineNo, noerror);
114 else
115 ret = tuiSetDisassemContent (lineOrAddr.addr);
116
117 if (ret == TUI_FAILURE)
118 {
119 tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
120 tuiClearExecInfoContent (winInfo);
121 }
122 else
123 {
124 tui_update_breakpoint_info (winInfo, 0);
125 tuiShowSourceContent (winInfo);
126 tuiUpdateExecInfo (winInfo);
127 if (winInfo->generic.type == SRC_WIN)
128 {
129 struct symtab_and_line sal;
130
131 sal.line = lineOrAddr.lineNo +
132 (winInfo->generic.contentSize - 2);
133 sal.symtab = s;
134 set_current_source_symtab_and_line (&sal);
135 /*
136 ** If the focus was in the asm win, put it in the src
137 ** win if we don't have a split layout
138 */
139 if (tuiWinWithFocus () == disassemWin &&
140 currentLayout () != SRC_DISASSEM_COMMAND)
141 tuiSetWinFocusTo (srcWin);
142 }
143 }
144
145
146 return;
147 } /* tuiUpdateSourceWindowAsIs */
148
149
150 /*
151 ** tuiUpdateSourceWindowsWithAddr().
152 ** Function to ensure that the source and/or disassemly windows
153 ** reflect the input address.
154 */
155 void
156 tuiUpdateSourceWindowsWithAddr (CORE_ADDR addr)
157 {
158 if (addr != 0)
159 {
160 struct symtab_and_line sal;
161 TuiLineOrAddress l;
162
163 switch (currentLayout ())
164 {
165 case DISASSEM_COMMAND:
166 case DISASSEM_DATA_COMMAND:
167 tuiShowDisassem (addr);
168 break;
169 case SRC_DISASSEM_COMMAND:
170 tuiShowDisassemAndUpdateSource (addr);
171 break;
172 default:
173 sal = find_pc_line (addr, 0);
174 l.lineNo = sal.line;
175 tuiShowSource (sal.symtab, l, FALSE);
176 break;
177 }
178 }
179 else
180 {
181 int i;
182
183 for (i = 0; i < (sourceWindows ())->count; i++)
184 {
185 TuiWinInfoPtr winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i];
186
187 tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
188 tuiClearExecInfoContent (winInfo);
189 }
190 }
191
192 return;
193 } /* tuiUpdateSourceWindowsWithAddr */
194
195 /*
196 ** tuiUpdateSourceWindowsWithLine().
197 ** Function to ensure that the source and/or disassemly windows
198 ** reflect the input address.
199 */
200 void
201 tuiUpdateSourceWindowsWithLine (struct symtab *s, int line)
202 {
203 CORE_ADDR pc;
204 TuiLineOrAddress l;
205
206 switch (currentLayout ())
207 {
208 case DISASSEM_COMMAND:
209 case DISASSEM_DATA_COMMAND:
210 find_line_pc (s, line, &pc);
211 tuiUpdateSourceWindowsWithAddr (pc);
212 break;
213 default:
214 l.lineNo = line;
215 tuiShowSource (s, l, FALSE);
216 if (currentLayout () == SRC_DISASSEM_COMMAND)
217 {
218 find_line_pc (s, line, &pc);
219 tuiShowDisassem (pc);
220 }
221 break;
222 }
223
224 return;
225 } /* tuiUpdateSourceWindowsWithLine */
226
227 /*
228 ** tuiClearSourceContent().
229 */
230 void
231 tuiClearSourceContent (TuiWinInfoPtr winInfo, int displayPrompt)
232 {
233 if (m_winPtrNotNull (winInfo))
234 {
235 register int i;
236
237 winInfo->generic.contentInUse = FALSE;
238 tuiEraseSourceContent (winInfo, displayPrompt);
239 for (i = 0; i < winInfo->generic.contentSize; i++)
240 {
241 TuiWinElementPtr element =
242 (TuiWinElementPtr) winInfo->generic.content[i];
243 element->whichElement.source.hasBreak = FALSE;
244 element->whichElement.source.isExecPoint = FALSE;
245 }
246 }
247
248 return;
249 } /* tuiClearSourceContent */
250
251
252 /*
253 ** tuiEraseSourceContent().
254 */
255 void
256 tuiEraseSourceContent (TuiWinInfoPtr winInfo, int displayPrompt)
257 {
258 int xPos;
259 int halfWidth = (winInfo->generic.width - 2) / 2;
260
261 if (winInfo->generic.handle != (WINDOW *) NULL)
262 {
263 werase (winInfo->generic.handle);
264 checkAndDisplayHighlightIfNeeded (winInfo);
265 if (displayPrompt == EMPTY_SOURCE_PROMPT)
266 {
267 char *noSrcStr;
268
269 if (winInfo->generic.type == SRC_WIN)
270 noSrcStr = NO_SRC_STRING;
271 else
272 noSrcStr = NO_DISASSEM_STRING;
273 if (strlen (noSrcStr) >= halfWidth)
274 xPos = 1;
275 else
276 xPos = halfWidth - strlen (noSrcStr);
277 mvwaddstr (winInfo->generic.handle,
278 (winInfo->generic.height / 2),
279 xPos,
280 noSrcStr);
281
282 /* elz: added this function call to set the real contents of
283 the window to what is on the screen, so that later calls
284 to refresh, do display
285 the correct stuff, and not the old image */
286
287 tuiSetSourceContentNil (winInfo, noSrcStr);
288 }
289 tuiRefreshWin (&winInfo->generic);
290 }
291 return;
292 } /* tuiEraseSourceContent */
293
294
295 /* Redraw the complete line of a source or disassembly window. */
296 static void
297 tui_show_source_line (TuiWinInfoPtr winInfo, int lineno)
298 {
299 TuiWinElementPtr line;
300 int x, y;
301
302 line = (TuiWinElementPtr) winInfo->generic.content[lineno - 1];
303 if (line->whichElement.source.isExecPoint)
304 wattron (winInfo->generic.handle, A_STANDOUT);
305
306 mvwaddstr (winInfo->generic.handle, lineno, 1,
307 line->whichElement.source.line);
308 if (line->whichElement.source.isExecPoint)
309 wattroff (winInfo->generic.handle, A_STANDOUT);
310
311 /* Clear to end of line but stop before the border. */
312 getyx (winInfo->generic.handle, y, x);
313 while (x + 1 < winInfo->generic.width)
314 {
315 waddch (winInfo->generic.handle, ' ');
316 getyx (winInfo->generic.handle, y, x);
317 }
318 }
319
320 /*
321 ** tuiShowSourceContent().
322 */
323 void
324 tuiShowSourceContent (TuiWinInfoPtr winInfo)
325 {
326 if (winInfo->generic.contentSize > 0)
327 {
328 int lineno;
329
330 for (lineno = 1; lineno <= winInfo->generic.contentSize; lineno++)
331 tui_show_source_line (winInfo, lineno);
332 }
333 else
334 tuiEraseSourceContent (winInfo, TRUE);
335
336 checkAndDisplayHighlightIfNeeded (winInfo);
337 tuiRefreshWin (&winInfo->generic);
338 winInfo->generic.contentInUse = TRUE;
339 }
340
341
342 /*
343 ** tuiHorizontalSourceScroll().
344 ** Scroll the source forward or backward horizontally
345 */
346 void
347 tuiHorizontalSourceScroll (TuiWinInfoPtr winInfo,
348 TuiScrollDirection direction,
349 int numToScroll)
350 {
351 if (winInfo->generic.content != (OpaquePtr) NULL)
352 {
353 int offset;
354 struct symtab *s;
355 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
356
357 if (cursal.symtab == (struct symtab *) NULL)
358 s = find_pc_symtab (selected_frame->pc);
359 else
360 s = cursal.symtab;
361
362 if (direction == LEFT_SCROLL)
363 offset = winInfo->detail.sourceInfo.horizontalOffset + numToScroll;
364 else
365 {
366 if ((offset =
367 winInfo->detail.sourceInfo.horizontalOffset - numToScroll) < 0)
368 offset = 0;
369 }
370 winInfo->detail.sourceInfo.horizontalOffset = offset;
371 tuiUpdateSourceWindowAsIs (
372 winInfo,
373 s,
374 ((TuiWinElementPtr)
375 winInfo->generic.content[0])->whichElement.source.lineOrAddr,
376 FALSE);
377 }
378
379 return;
380 } /* tuiHorizontalSourceScroll */
381
382
383 /* Set or clear the hasBreak flag in the line whose line is lineNo. */
384 void
385 tuiSetIsExecPointAt (TuiLineOrAddress l, TuiWinInfoPtr winInfo)
386 {
387 int changed = 0;
388 int i;
389 TuiWinContent content = (TuiWinContent) winInfo->generic.content;
390
391 i = 0;
392 while (i < winInfo->generic.contentSize)
393 {
394 int newState;
395
396 if (content[i]->whichElement.source.lineOrAddr.addr == l.addr)
397 newState = TRUE;
398 else
399 newState = FALSE;
400 if (newState != content[i]->whichElement.source.isExecPoint)
401 {
402 changed++;
403 content[i]->whichElement.source.isExecPoint = newState;
404 tui_show_source_line (winInfo, i + 1);
405 }
406 i++;
407 }
408 if (changed)
409 tuiRefreshWin (&winInfo->generic);
410 }
411
412 /* Update the execution windows to show the active breakpoints.
413 This is called whenever a breakpoint is inserted, removed or
414 has its state changed. */
415 void
416 tui_update_all_breakpoint_info ()
417 {
418 TuiList* list = sourceWindows ();
419 int i;
420
421 for (i = 0; i < list->count; i++)
422 {
423 TuiWinInfoPtr win = (TuiWinInfoPtr) list->list[i];
424
425 if (tui_update_breakpoint_info (win, FALSE))
426 {
427 tuiUpdateExecInfo (win);
428 }
429 }
430 }
431
432
433 /* Scan the source window and the breakpoints to update the
434 hasBreak information for each line.
435 Returns 1 if something changed and the execution window
436 must be refreshed. */
437 int
438 tui_update_breakpoint_info (TuiWinInfoPtr win, int current_only)
439 {
440 int i;
441 int need_refresh = 0;
442 TuiSourceInfoPtr src = &win->detail.sourceInfo;
443
444 for (i = 0; i < win->generic.contentSize; i++)
445 {
446 struct breakpoint *bp;
447 extern struct breakpoint *breakpoint_chain;
448 int mode;
449 TuiSourceElement* line;
450
451 line = &((TuiWinElementPtr) win->generic.content[i])->whichElement.source;
452 if (current_only && !line->isExecPoint)
453 continue;
454
455 /* Scan each breakpoint to see if the current line has something to
456 do with it. Identify enable/disabled breakpoints as well as
457 those that we already hit. */
458 mode = 0;
459 for (bp = breakpoint_chain;
460 bp != (struct breakpoint *) NULL;
461 bp = bp->next)
462 {
463 if ((win == srcWin
464 && bp->source_file
465 && (strcmp (src->filename, bp->source_file) == 0)
466 && bp->line_number == line->lineOrAddr.lineNo)
467 || (win == disassemWin
468 && bp->address == line->lineOrAddr.addr))
469 {
470 if (bp->enable_state == bp_disabled)
471 mode |= TUI_BP_DISABLED;
472 else
473 mode |= TUI_BP_ENABLED;
474 if (bp->hit_count)
475 mode |= TUI_BP_HIT;
476 if (bp->cond)
477 mode |= TUI_BP_CONDITIONAL;
478 if (bp->type == bp_hardware_breakpoint)
479 mode |= TUI_BP_HARDWARE;
480 }
481 }
482 if (line->hasBreak != mode)
483 {
484 line->hasBreak = mode;
485 need_refresh = 1;
486 }
487 }
488 return need_refresh;
489 }
490
491
492 /*
493 ** tuiSetExecInfoContent().
494 ** Function to initialize the content of the execution info window,
495 ** based upon the input window which is either the source or
496 ** disassembly window.
497 */
498 TuiStatus
499 tuiSetExecInfoContent (TuiWinInfoPtr winInfo)
500 {
501 TuiStatus ret = TUI_SUCCESS;
502
503 if (winInfo->detail.sourceInfo.executionInfo != (TuiGenWinInfoPtr) NULL)
504 {
505 TuiGenWinInfoPtr execInfoPtr = winInfo->detail.sourceInfo.executionInfo;
506
507 if (execInfoPtr->content == (OpaquePtr) NULL)
508 execInfoPtr->content =
509 (OpaquePtr) allocContent (winInfo->generic.height,
510 execInfoPtr->type);
511 if (execInfoPtr->content != (OpaquePtr) NULL)
512 {
513 int i;
514
515 tui_update_breakpoint_info (winInfo, 1);
516 for (i = 0; i < winInfo->generic.contentSize; i++)
517 {
518 TuiWinElementPtr element;
519 TuiWinElementPtr srcElement;
520 int mode;
521
522 element = (TuiWinElementPtr) execInfoPtr->content[i];
523 srcElement = (TuiWinElementPtr) winInfo->generic.content[i];
524
525 memset(element->whichElement.simpleString, ' ',
526 sizeof(element->whichElement.simpleString));
527 element->whichElement.simpleString[TUI_EXECINFO_SIZE - 1] = 0;
528
529 /* Now update the exec info content based upon the state
530 of each line as indicated by the source content. */
531 mode = srcElement->whichElement.source.hasBreak;
532 if (mode & TUI_BP_HIT)
533 element->whichElement.simpleString[TUI_BP_HIT_POS] =
534 (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
535 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
536 element->whichElement.simpleString[TUI_BP_HIT_POS] =
537 (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
538
539 if (mode & TUI_BP_ENABLED)
540 element->whichElement.simpleString[TUI_BP_BREAK_POS] = '+';
541 else if (mode & TUI_BP_DISABLED)
542 element->whichElement.simpleString[TUI_BP_BREAK_POS] = '-';
543
544 if (srcElement->whichElement.source.isExecPoint)
545 element->whichElement.simpleString[TUI_EXEC_POS] = '>';
546 }
547 execInfoPtr->contentSize = winInfo->generic.contentSize;
548 }
549 else
550 ret = TUI_FAILURE;
551 }
552
553 return ret;
554 }
555
556
557 /*
558 ** tuiShowExecInfoContent().
559 */
560 void
561 tuiShowExecInfoContent (TuiWinInfoPtr winInfo)
562 {
563 TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
564 int curLine;
565
566 werase (execInfo->handle);
567 tuiRefreshWin (execInfo);
568 for (curLine = 1; (curLine <= execInfo->contentSize); curLine++)
569 mvwaddstr (execInfo->handle,
570 curLine,
571 0,
572 ((TuiWinElementPtr)
573 execInfo->content[curLine - 1])->whichElement.simpleString);
574 tuiRefreshWin (execInfo);
575 execInfo->contentInUse = TRUE;
576
577 return;
578 } /* tuiShowExecInfoContent */
579
580
581 /*
582 ** tuiEraseExecInfoContent().
583 */
584 void
585 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo)
586 {
587 TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
588
589 werase (execInfo->handle);
590 tuiRefreshWin (execInfo);
591
592 return;
593 } /* tuiEraseExecInfoContent */
594
595 /*
596 ** tuiClearExecInfoContent().
597 */
598 void
599 tuiClearExecInfoContent (TuiWinInfoPtr winInfo)
600 {
601 winInfo->detail.sourceInfo.executionInfo->contentInUse = FALSE;
602 tuiEraseExecInfoContent (winInfo);
603
604 return;
605 } /* tuiClearExecInfoContent */
606
607 /*
608 ** tuiUpdateExecInfo().
609 ** Function to update the execution info window
610 */
611 void
612 tuiUpdateExecInfo (TuiWinInfoPtr winInfo)
613 {
614 tuiSetExecInfoContent (winInfo);
615 tuiShowExecInfoContent (winInfo);
616 } /* tuiUpdateExecInfo */
617
618 TuiStatus
619 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo)
620 {
621 register char *srcLineBuf;
622 register int i, lineWidth, maxLines;
623 TuiStatus ret = TUI_FAILURE;
624
625 maxLines = winInfo->generic.height; /* less the highlight box */
626 lineWidth = winInfo->generic.width - 1;
627 /*
628 ** Allocate the buffer for the source lines. Do this only once since they
629 ** will be re-used for all source displays. The only other time this will
630 ** be done is when a window's size changes.
631 */
632 if (winInfo->generic.content == (OpaquePtr) NULL)
633 {
634 srcLineBuf = (char *) xmalloc ((maxLines * lineWidth) * sizeof (char));
635 if (srcLineBuf == (char *) NULL)
636 fputs_unfiltered (
637 "Unable to Allocate Memory for Source or Disassembly Display.\n",
638 gdb_stderr);
639 else
640 {
641 /* allocate the content list */
642 if ((winInfo->generic.content =
643 (OpaquePtr) allocContent (maxLines, SRC_WIN)) == (OpaquePtr) NULL)
644 {
645 tuiFree (srcLineBuf);
646 srcLineBuf = (char *) NULL;
647 fputs_unfiltered (
648 "Unable to Allocate Memory for Source or Disassembly Display.\n",
649 gdb_stderr);
650 }
651 }
652 for (i = 0; i < maxLines; i++)
653 ((TuiWinElementPtr)
654 winInfo->generic.content[i])->whichElement.source.line =
655 srcLineBuf + (lineWidth * i);
656 ret = TUI_SUCCESS;
657 }
658 else
659 ret = TUI_SUCCESS;
660
661 return ret;
662 } /* tuiAllocSourceBuffer */
663
664
665 /*
666 ** tuiLineIsDisplayed().
667 ** Answer whether the a particular line number or address is displayed
668 ** in the current source window.
669 */
670 int
671 tuiLineIsDisplayed (int line, TuiWinInfoPtr winInfo,
672 int checkThreshold)
673 {
674 int isDisplayed = FALSE;
675 int i, threshold;
676
677 if (checkThreshold)
678 threshold = SCROLL_THRESHOLD;
679 else
680 threshold = 0;
681 i = 0;
682 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
683 {
684 isDisplayed = (((TuiWinElementPtr)
685 winInfo->generic.content[i])->whichElement.source.lineOrAddr.lineNo
686 == (int) line);
687 i++;
688 }
689
690 return isDisplayed;
691 } /* tuiLineIsDisplayed */
692
693
694 /*
695 ** tuiLineIsDisplayed().
696 ** Answer whether the a particular line number or address is displayed
697 ** in the current source window.
698 */
699 int
700 tuiAddrIsDisplayed (CORE_ADDR addr, TuiWinInfoPtr winInfo,
701 int checkThreshold)
702 {
703 int isDisplayed = FALSE;
704 int i, threshold;
705
706 if (checkThreshold)
707 threshold = SCROLL_THRESHOLD;
708 else
709 threshold = 0;
710 i = 0;
711 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
712 {
713 isDisplayed = (((TuiWinElementPtr)
714 winInfo->generic.content[i])->whichElement.source.lineOrAddr.addr
715 == addr);
716 i++;
717 }
718
719 return isDisplayed;
720 }
721
722
723 /*****************************************
724 ** STATIC LOCAL FUNCTIONS **
725 ******************************************/
This page took 0.067872 seconds and 4 git commands to generate.