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