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