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