* target.h: Add to_doc and target_preopen.
[deliverable/binutils-gdb.git] / gdb / source.c
CommitLineData
bd5635a1
RP
1/* List lines of source files for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6GDB is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GDB is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GDB; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include <stdio.h>
21#include "defs.h"
22#include "symtab.h"
23#include "param.h"
24#include "command.h"
25#include "frame.h"
26
27#ifdef USG
28#include <sys/types.h>
29#endif
30
31#include <string.h>
32#include <sys/param.h>
33#include <sys/stat.h>
34#include <fcntl.h>
35#include "gdbcore.h"
36
37extern char *strstr();
38
39extern void set_next_address ();
40
41void mod_path ();
42
43/* Path of directories to search for source files.
44 Same format as the PATH environment variable's value. */
45
46char *source_path;
47
48/* Symtab of default file for listing lines of. */
49
50struct symtab *current_source_symtab;
51
52/* Default next line to list. */
53
54int current_source_line;
55
56/* Line number of last line printed. Default for various commands.
57 current_source_line is usually, but not always, the same as this. */
58
59static int last_line_listed;
60
61/* First line number listed by last listing command. */
62
63static int first_line_listed;
64
65\f
66/* Set the source file default for the "list" command, specifying a
67 symtab. Sigh. Behavior specification: If it is called with a
68 non-zero argument, that is the symtab to select. If it is not,
69 first lookup "main"; if it exists, use the symtab and line it
70 defines. If not, take the last symtab in the symtab_list (if it
71 exists) or the last symtab in the psymtab_list (if *it* exists). If
72 none of this works, report an error. */
73
74void
75select_source_symtab (s)
76 register struct symtab *s;
77{
78 struct symtabs_and_lines sals;
79 struct symtab_and_line sal;
80 struct partial_symtab *ps;
81 struct partial_symtab *cs_pst = 0;
82
83 if (s)
84 {
85 current_source_symtab = s;
86 current_source_line = 1;
87 return;
88 }
89
90 /* Make the default place to list be the function `main'
91 if one exists. */
92 if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0, NULL))
93 {
94 sals = decode_line_spec ("main", 1);
95 sal = sals.sals[0];
96 free (sals.sals);
97 current_source_symtab = sal.symtab;
98 current_source_line = max (sal.line - (lines_to_list () - 1), 1);
99 return;
100 }
101
102 /* All right; find the last file in the symtab list (ignoring .h's). */
103
104 if (s = symtab_list)
105 {
106 do
107 {
108 char *name = s->filename;
109 int len = strlen (name);
110 if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
111 current_source_symtab = s;
112 s = s->next;
113 }
114 while (s);
115 current_source_line = 1;
116 }
117 else if (partial_symtab_list)
118 {
119 ps = partial_symtab_list;
120 while (ps)
121 {
122 char *name = ps->filename;
123 int len = strlen (name);
124 if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
125 cs_pst = ps;
126 ps = ps->next;
127 }
128 if (cs_pst)
129 if (cs_pst->readin)
130 fatal ("Internal: select_source_symtab: readin pst found and no symtabs.");
131 else
132 current_source_symtab = PSYMTAB_TO_SYMTAB (cs_pst);
133 else
134 current_source_symtab = 0;
135 current_source_line = 1;
136 }
137}
138\f
139static void
140directories_info ()
141{
142 printf ("Source directories searched: %s\n", source_path);
143}
144
145/* Forget what we learned about line positions in source files,
146 and which directories contain them;
147 must check again now since files may be found in
148 a different directory now. */
149
150void
151forget_cached_source_info ()
152{
153 register struct symtab *s;
154
155 for (s = symtab_list; s; s = s->next)
156 {
157 if (s->line_charpos != 0)
158 {
159 free (s->line_charpos);
160 s->line_charpos = 0;
161 }
162 if (s->fullname != 0)
163 {
164 free (s->fullname);
165 s->fullname = 0;
166 }
167 }
168}
169
170void
171init_source_path ()
172{
173 source_path = savestring ("$cdir:$cwd", /* strlen of it */ 10);
174 forget_cached_source_info ();
175}
176
177/* Add zero or more directories to the front of the source path. */
178
179void
180directory_command (dirname, from_tty)
181 char *dirname;
182 int from_tty;
183{
184 dont_repeat ();
185 /* FIXME, this goes to "delete dir"... */
186 if (dirname == 0)
187 {
188 if (query ("Reinitialize source path to empty? ", ""))
189 {
190 free (source_path);
191 init_source_path ();
192 }
193 }
194 else
195 mod_path (dirname, from_tty, &source_path);
196 if (from_tty)
197 directories_info ();
198 forget_cached_source_info ();
199}
200
201/* Add zero or more directories to the front of an arbitrary path. */
202
203void
204mod_path (dirname, from_tty, which_path)
205 char *dirname;
206 int from_tty;
207 char **which_path;
208{
209 char *old = *which_path;
210 int prefix = 0;
211
212 if (dirname == 0)
213 return;
214
215 dirname = strsave (dirname);
216 make_cleanup (free, dirname);
217
218 do
219 {
220 extern char *index ();
221 char *name = dirname;
222 register char *p;
223 struct stat st;
224
225 {
226 char *colon = index (name, ':');
227 char *space = index (name, ' ');
228 char *tab = index (name, '\t');
229 if (colon == 0 && space == 0 && tab == 0)
230 p = dirname = name + strlen (name);
231 else
232 {
233 p = 0;
234 if (colon != 0 && (p == 0 || colon < p))
235 p = colon;
236 if (space != 0 && (p == 0 || space < p))
237 p = space;
238 if (tab != 0 && (p == 0 || tab < p))
239 p = tab;
240 dirname = p + 1;
241 while (*dirname == ':' || *dirname == ' ' || *dirname == '\t')
242 ++dirname;
243 }
244 }
245
246 if (p[-1] == '/')
247 /* Sigh. "foo/" => "foo" */
248 --p;
249 *p = '\0';
250
251 while (p[-1] == '.')
252 {
253 if (p - name == 1)
254 {
255 /* "." => getwd (). */
256 name = current_directory;
257 goto append;
258 }
259 else if (p[-2] == '/')
260 {
261 if (p - name == 2)
262 {
263 /* "/." => "/". */
264 *--p = '\0';
265 goto append;
266 }
267 else
268 {
269 /* "...foo/." => "...foo". */
270 p -= 2;
271 *p = '\0';
272 continue;
273 }
274 }
275 else
276 break;
277 }
278
279 if (name[0] == '~')
280 name = tilde_expand (name);
281 else if (name[0] != '/' && name[0] != '$')
282 name = concat (current_directory, "/", name);
283 else
284 name = savestring (name, p - name);
285 make_cleanup (free, name);
286
287 /* Unless it's a variable, check existence. */
288 if (name[0] != '$') {
289 if (stat (name, &st) < 0)
290 perror_with_name (name);
291 if ((st.st_mode & S_IFMT) != S_IFDIR)
292 error ("%s is not a directory.", name);
293 }
294
295 append:
296 {
297 register unsigned int len = strlen (name);
298
299 p = *which_path;
300 while (1)
301 {
302 if (!strncmp (p, name, len)
303 && (p[len] == '\0' || p[len] == ':'))
304 {
305 /* Found it in the search path, remove old copy */
306 if (p > *which_path)
307 p--; /* Back over leading colon */
308 if (prefix > p - *which_path)
309 goto skip_dup; /* Same dir twice in one cmd */
310 strcpy (p, &p[len+1]); /* Copy from next \0 or : */
311 }
312 p = index (p, ':');
313 if (p != 0)
314 ++p;
315 else
316 break;
317 }
318 if (p == 0)
319 {
320 /* If we have already tacked on a name(s) in this command, be sure they stay on the front as we tack on some more. */
321 if (prefix)
322 {
323 char *temp, c;
324
325 c = old[prefix];
326 old[prefix] = '\0';
327 temp = concat (old, ":", name);
328 old[prefix] = c;
329 *which_path = concat (temp, "", &old[prefix]);
330 prefix = strlen (temp);
331 free (temp);
332 }
333 else
334 {
335 *which_path = concat (name, (old[0]? ":" : old), old);
336 prefix = strlen (name);
337 }
338 free (old);
339 old = *which_path;
340 }
341 }
342 skip_dup: ;
343 } while (*dirname != '\0');
344}
345
346
347static void
348source_info ()
349{
350 register struct symtab *s = current_source_symtab;
351
352 if (!s)
353 {
354 printf("No current source file.\n");
355 return;
356 }
357 printf ("Current source file is %s\n", s->filename);
358 if (s->dirname)
359 printf ("Compilation directory is %s\n", s->dirname);
360 if (s->fullname)
361 printf ("Located in %s\n", s->fullname);
362 if (s->nlines)
363 printf ("Contains %d lines\n", s->nlines);
364
365 switch (s->language) {
366 case language_c:
367 printf("Written in the C language.\n");
368 /* Add more cases here when -Wswitch complains... */
369 case language_unknown:
370 break;
371 }
372}
373
374
375\f
376/* Open a file named STRING, searching path PATH (dir names sep by colons)
377 using mode MODE and protection bits PROT in the calls to open.
378 If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
379 (ie pretend the first element of PATH is ".")
380 If FILENAMED_OPENED is non-null, set it to a newly allocated string naming
381 the actual file opened (this string will always start with a "/". We
382 have to take special pains to avoid doubling the "/" between the directory
383 and the file, sigh! Emacs gets confuzzed by this when we print the
384 source file name!!!
385
386 If a file is found, return the descriptor.
387 Otherwise, return -1, with errno set for the last name we tried to open. */
388
389/* >>>> This should only allow files of certain types,
390 >>>> eg executable, non-directory */
391int
392openp (path, try_cwd_first, string, mode, prot, filename_opened)
393 char *path;
394 int try_cwd_first;
395 char *string;
396 int mode;
397 int prot;
398 char **filename_opened;
399{
400 register int fd;
401 register char *filename;
402 register char *p, *p1;
403 register int len;
404 int alloclen;
405
406 if (!path)
407 path = ".";
408
409 /* ./foo => foo */
410 while (string[0] == '.' && string[1] == '/')
411 string += 2;
412
413 if (try_cwd_first || string[0] == '/')
414 {
415 filename = string;
416 fd = open (filename, mode, prot);
417 if (fd >= 0 || string[0] == '/')
418 goto done;
419 }
420
421 alloclen = strlen (path) + strlen (string) + 2;
422 filename = (char *) alloca (alloclen);
423 fd = -1;
424 for (p = path; p; p = p1 ? p1 + 1 : 0)
425 {
426 p1 = (char *) index (p, ':');
427 if (p1)
428 len = p1 - p;
429 else
430 len = strlen (p);
431
432 if (len == 4 && p[0] == '$' && p[1] == 'c'
433 && p[2] == 'w' && p[3] == 'd') {
434 /* Name is $cwd -- insert current directory name instead. */
435 int newlen;
436
437 /* First, realloc the filename buffer if too short. */
438 len = strlen (current_directory);
439 newlen = len + strlen (string) + 2;
440 if (newlen > alloclen) {
441 alloclen = newlen;
442 filename = (char *) alloca (alloclen);
443 }
444 strcpy (filename, current_directory);
445 } else {
446 /* Normal file name in path -- just use it. */
447 strncpy (filename, p, len);
448 filename[len] = 0;
449 }
450
451 /* Beware the // my son, the Emacs barfs, the botch that catch... */
452 while (len > 1 && filename[len-1] == '/')
453 filename[--len] = 0;
454 strcat (filename+len, "/");
455 strcat (filename, string);
456
457 fd = open (filename, mode, prot);
458 if (fd >= 0) break;
459 }
460
461 done:
462 if (filename_opened)
463 if (fd < 0)
464 *filename_opened = (char *) 0;
465 else if (filename[0] == '/')
466 *filename_opened = savestring (filename, strlen (filename));
467 else
468 {
469 /* Beware the // my son, the Emacs barfs, the botch that catch... */
470
471 *filename_opened = concat (current_directory,
472 '/' == current_directory[strlen(current_directory)-1]? "": "/",
473 filename);
474 }
475
476 return fd;
477}
478
479/* Open a source file given a symtab S. Returns a file descriptor
480 or negative number for error. */
481int
482open_source_file (s)
483 struct symtab *s;
484{
485 char *path = source_path;
486 char *p;
487 int result;
488
489 /* Quick way out if we already know its full name */
490 if (s->fullname)
491 {
492 result = open (s->fullname, O_RDONLY);
493 if (result >= 0)
494 return result;
495 /* Didn't work -- free old one, try again. */
496 free (s->fullname);
497 s->fullname = NULL;
498 }
499
500 if (s->dirname != NULL)
501 {
502 /* Replace a path entry of $cdir with the compilation directory name */
503#define cdir_len 5
504 p = strstr (source_path, "$cdir");
505 if (p && (p == path || p[-1] == ':')
506 && (p[cdir_len] == ':' || p[cdir_len] == '\0')) {
507 int len;
508
509 path = (char *)
510 alloca (strlen (source_path) + 1 + strlen (s->dirname) + 1);
511 len = p - source_path;
512 strncpy (path, source_path, len); /* Before $cdir */
513 strcpy (path + len, s->dirname); /* new stuff */
514 strcat (path + len, source_path + len + cdir_len); /* After $cdir */
515 }
516 }
517
518 return openp (path, 0, s->filename, O_RDONLY, 0, &s->fullname);
519}
520
521\f
522/* Create and initialize the table S->line_charpos that records
523 the positions of the lines in the source file, which is assumed
524 to be open on descriptor DESC.
525 All set S->nlines to the number of such lines. */
526
527static void
528find_source_lines (s, desc)
529 struct symtab *s;
530 int desc;
531{
532 struct stat st;
533 register char *data, *p, *end;
534 int nlines = 0;
535 int lines_allocated = 1000;
536 int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
537
538 if (fstat (desc, &st) < 0)
539 perror_with_name (s->filename);
540 if (exec_bfd && bfd_get_mtime(exec_bfd) < st.st_mtime)
541 printf ("Source file is more recent than executable.\n");
542
543#if defined (BROKEN_LARGE_ALLOCA)
544 data = (char *) xmalloc (st.st_size);
545 make_cleanup (free, data);
546#else
547 data = (char *) alloca (st.st_size);
548#endif
549 if (myread (desc, data, st.st_size) < 0)
550 perror_with_name (s->filename);
551 end = data + st.st_size;
552 p = data;
553 line_charpos[0] = 0;
554 nlines = 1;
555 while (p != end)
556 {
557 if (*p++ == '\n'
558 /* A newline at the end does not start a new line. */
559 && p != end)
560 {
561 if (nlines == lines_allocated)
562 {
563 lines_allocated *= 2;
564 line_charpos = (int *) xrealloc (line_charpos,
565 sizeof (int) * lines_allocated);
566 }
567 line_charpos[nlines++] = p - data;
568 }
569 }
570 s->nlines = nlines;
571 s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
572}
573
574/* Return the character position of a line LINE in symtab S.
575 Return 0 if anything is invalid. */
576
577int
578source_line_charpos (s, line)
579 struct symtab *s;
580 int line;
581{
582 if (!s) return 0;
583 if (!s->line_charpos || line <= 0) return 0;
584 if (line > s->nlines)
585 line = s->nlines;
586 return s->line_charpos[line - 1];
587}
588
589/* Return the line number of character position POS in symtab S. */
590
591int
592source_charpos_line (s, chr)
593 register struct symtab *s;
594 register int chr;
595{
596 register int line = 0;
597 register int *lnp;
598
599 if (s == 0 || s->line_charpos == 0) return 0;
600 lnp = s->line_charpos;
601 /* Files are usually short, so sequential search is Ok */
602 while (line < s->nlines && *lnp <= chr)
603 {
604 line++;
605 lnp++;
606 }
607 if (line >= s->nlines)
608 line = s->nlines;
609 return line;
610}
611\f
612/* Get full pathname and line number positions for a symtab.
613 Return nonzero if line numbers may have changed.
614 Set *FULLNAME to actual name of the file as found by `openp',
615 or to 0 if the file is not found. */
616
617int
618get_filename_and_charpos (s, fullname)
619 struct symtab *s;
620 char **fullname;
621{
622 register int desc, linenums_changed = 0;
623
624 desc = open_source_file (s);
625 if (desc < 0)
626 {
627 if (fullname)
628 *fullname = NULL;
629 return 0;
630 }
631 if (fullname)
632 *fullname = s->fullname;
633 if (s->line_charpos == 0) linenums_changed = 1;
634 if (linenums_changed) find_source_lines (s, desc);
635 close (desc);
636 return linenums_changed;
637}
638
639/* Print text describing the full name of the source file S
640 and the line number LINE and its corresponding character position.
641 The text starts with two Ctrl-z so that the Emacs-GDB interface
642 can easily find it.
643
644 MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
645
646 Return 1 if successful, 0 if could not find the file. */
647
648int
649identify_source_line (s, line, mid_statement)
650 struct symtab *s;
651 int line;
652 int mid_statement;
653{
654 if (s->line_charpos == 0)
655 get_filename_and_charpos (s, (char **)NULL);
656 if (s->fullname == 0)
657 return 0;
658 printf ("\032\032%s:%d:%d:%s:0x%x\n", s->fullname,
659 line, s->line_charpos[line - 1],
660 mid_statement ? "middle" : "beg",
661 get_frame_pc (get_current_frame()));
662 current_source_line = line;
663 first_line_listed = line;
664 last_line_listed = line;
665 current_source_symtab = s;
666 return 1;
667}
668\f
669/* Print source lines from the file of symtab S,
670 starting with line number LINE and stopping before line number STOPLINE. */
671
672void
673print_source_lines (s, line, stopline, noerror)
674 struct symtab *s;
675 int line, stopline;
676 int noerror;
677{
678 register int c;
679 register int desc;
680 register FILE *stream;
681 int nlines = stopline - line;
682
683 /* Regardless of whether we can open the file, set current_source_symtab. */
684 current_source_symtab = s;
685 current_source_line = line;
686 first_line_listed = line;
687
688 desc = open_source_file (s);
689 if (desc < 0)
690 {
691 if (! noerror) {
692 char *name = alloca (strlen (s->filename) + 100);
693 sprintf (name, "%s:%d", s->filename, line);
694 print_sys_errmsg (name, errno);
695 }
696 return;
697 }
698
699 if (s->line_charpos == 0)
700 find_source_lines (s, desc);
701
702 if (line < 1 || line > s->nlines)
703 {
704 close (desc);
705 error ("Line number %d out of range; %s has %d lines.",
706 line, s->filename, s->nlines);
707 }
708
709 if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
710 {
711 close (desc);
712 perror_with_name (s->filename);
713 }
714
715 stream = fdopen (desc, "r");
716 clearerr (stream);
717
718 while (nlines-- > 0)
719 {
720 c = fgetc (stream);
721 if (c == EOF) break;
722 last_line_listed = current_source_line;
723 printf_filtered ("%d\t", current_source_line++);
724 do
725 {
726 if (c < 040 && c != '\t' && c != '\n')
727 printf_filtered ("^%c", c + 0100);
728 else if (c == 0177)
729 printf_filtered ("^?");
730 else
731 printf_filtered ("%c", c);
732 } while (c != '\n' && (c = fgetc (stream)) >= 0);
733 }
734
735 fclose (stream);
736}
737\f
738
739
740/*
741 C++
742 Print a list of files and line numbers which a user may choose from
743 in order to list a function which was specified ambiguously
744 (as with `list classname::overloadedfuncname', for example).
745 The vector in SALS provides the filenames and line numbers.
746 */
747static void
748ambiguous_line_spec (sals)
749 struct symtabs_and_lines *sals;
750{
751 int i;
752
753 for (i = 0; i < sals->nelts; ++i)
754 printf("file: \"%s\", line number: %d\n",
755 sals->sals[i].symtab->filename, sals->sals[i].line);
756}
757
758
759static void
760list_command (arg, from_tty)
761 char *arg;
762 int from_tty;
763{
764 struct symtabs_and_lines sals, sals_end;
765 struct symtab_and_line sal, sal_end;
766 struct symbol *sym;
767 char *arg1;
768 int no_end = 1;
769 int dummy_end = 0;
770 int dummy_beg = 0;
771 int linenum_beg = 0;
772 char *p;
773
774 if (symtab_list == 0 && partial_symtab_list == 0)
775 error ("No symbol table is loaded. Use the \"symbol-file\" command.");
776
777 /* Pull in a current source symtab if necessary */
778 if (current_source_symtab == 0 &&
779 (arg == 0 || arg[0] == '+' || arg[0] == '-'))
780 select_source_symtab (0);
781
782 /* "l" or "l +" lists next ten lines. */
783
784 if (arg == 0 || !strcmp (arg, "+"))
785 {
786 if (current_source_symtab == 0)
787 error ("No default source file yet. Do \"help list\".");
788 print_source_lines (current_source_symtab, current_source_line,
789 current_source_line + lines_to_list (), 0);
790 return;
791 }
792
793 /* "l -" lists previous ten lines, the ones before the ten just listed. */
794 if (!strcmp (arg, "-"))
795 {
796 if (current_source_symtab == 0)
797 error ("No default source file yet. Do \"help list\".");
798 print_source_lines (current_source_symtab,
799 max (first_line_listed - lines_to_list (), 1),
800 first_line_listed, 0);
801 return;
802 }
803
804 /* Now if there is only one argument, decode it in SAL
805 and set NO_END.
806 If there are two arguments, decode them in SAL and SAL_END
807 and clear NO_END; however, if one of the arguments is blank,
808 set DUMMY_BEG or DUMMY_END to record that fact. */
809
810 arg1 = arg;
811 if (*arg1 == ',')
812 dummy_beg = 1;
813 else
814 {
815 sals = decode_line_1 (&arg1, 0, 0, 0);
816
817 if (! sals.nelts) return; /* C++ */
818 if (sals.nelts > 1)
819 {
820 ambiguous_line_spec (&sals);
821 free (sals.sals);
822 return;
823 }
824
825 sal = sals.sals[0];
826 free (sals.sals);
827 }
828
829 /* Record whether the BEG arg is all digits. */
830
831 for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
832 linenum_beg = (p == arg1);
833
834 while (*arg1 == ' ' || *arg1 == '\t')
835 arg1++;
836 if (*arg1 == ',')
837 {
838 no_end = 0;
839 arg1++;
840 while (*arg1 == ' ' || *arg1 == '\t')
841 arg1++;
842 if (*arg1 == 0)
843 dummy_end = 1;
844 else
845 {
846 if (dummy_beg)
847 sals_end = decode_line_1 (&arg1, 0, 0, 0);
848 else
849 sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
850 if (sals_end.nelts == 0)
851 return;
852 if (sals_end.nelts > 1)
853 {
854 ambiguous_line_spec (&sals_end);
855 free (sals_end.sals);
856 return;
857 }
858 sal_end = sals_end.sals[0];
859 free (sals_end.sals);
860 }
861 }
862
863 if (*arg1)
864 error ("Junk at end of line specification.");
865
866 if (!no_end && !dummy_beg && !dummy_end
867 && sal.symtab != sal_end.symtab)
868 error ("Specified start and end are in different files.");
869 if (dummy_beg && dummy_end)
870 error ("Two empty args do not say what lines to list.");
871
872 /* if line was specified by address,
873 first print exactly which line, and which file.
874 In this case, sal.symtab == 0 means address is outside
875 of all known source files, not that user failed to give a filename. */
876 if (*arg == '*')
877 {
878 if (sal.symtab == 0)
879 error ("No source file for address 0x%x.", sal.pc);
880 sym = find_pc_function (sal.pc);
881 if (sym)
882 printf ("0x%x is in %s (%s, line %d).\n",
883 sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
884 else
885 printf ("0x%x is in %s, line %d.\n",
886 sal.pc, sal.symtab->filename, sal.line);
887 }
888
889 /* If line was not specified by just a line number,
890 and it does not imply a symtab, it must be an undebuggable symbol
891 which means no source code. */
892
893 if (! linenum_beg && sal.symtab == 0)
894 error ("No line number known for %s.", arg);
895
896 /* If this command is repeated with RET,
897 turn it into the no-arg variant. */
898
899 if (from_tty)
900 *arg = 0;
901
902 if (dummy_beg && sal_end.symtab == 0)
903 error ("No default source file yet. Do \"help list\".");
904 if (dummy_beg)
905 print_source_lines (sal_end.symtab,
906 max (sal_end.line - (lines_to_list () - 1), 1),
907 sal_end.line + 1, 0);
908 else if (sal.symtab == 0)
909 error ("No default source file yet. Do \"help list\".");
910 else if (no_end)
911 print_source_lines (sal.symtab,
912 max (sal.line - (lines_to_list () / 2), 1),
913 sal.line + 5, 0);
914 else
915 print_source_lines (sal.symtab, sal.line,
916 (dummy_end
917 ? sal.line + lines_to_list ()
918 : sal_end.line + 1),
919 0);
920}
921\f
922/* Print info on range of pc's in a specified line. */
923
924static void
925line_info (arg, from_tty)
926 char *arg;
927 int from_tty;
928{
929 struct symtabs_and_lines sals;
930 struct symtab_and_line sal;
931 CORE_ADDR start_pc, end_pc;
932 int i;
933
934 if (arg == 0)
935 {
936 sal.symtab = current_source_symtab;
937 sal.line = last_line_listed;
938 sals.nelts = 1;
939 sals.sals = (struct symtab_and_line *)
940 xmalloc (sizeof (struct symtab_and_line));
941 sals.sals[0] = sal;
942 }
943 else
944 {
945 sals = decode_line_spec_1 (arg, 0);
946
947 /* If this command is repeated with RET,
948 turn it into the no-arg variant. */
949 if (from_tty)
950 *arg = 0;
951 }
952
953 /* C++ More than one line may have been specified, as when the user
954 specifies an overloaded function name. Print info on them all. */
955 for (i = 0; i < sals.nelts; i++)
956 {
957 sal = sals.sals[i];
958
959 if (sal.symtab == 0)
960 error ("No source file specified.");
961
962 if (sal.line > 0
963 && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
964 {
965 if (start_pc == end_pc)
966 printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n",
967 sal.line, sal.symtab->filename, start_pc);
968 else
969 printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n",
970 sal.line, sal.symtab->filename, start_pc, end_pc);
971 /* x/i should display this line's code. */
972 set_next_address (start_pc);
973 /* Repeating "info line" should do the following line. */
974 last_line_listed = sal.line + 1;
975 }
976 else
977 printf ("Line number %d is out of range for \"%s\".\n",
978 sal.line, sal.symtab->filename);
979 }
980}
981\f
982/* Commands to search the source file for a regexp. */
983
984static void
985forward_search_command (regex, from_tty)
986 char *regex;
987 int from_tty;
988{
989 register int c;
990 register int desc;
991 register FILE *stream;
992 int line = last_line_listed + 1;
993 char *msg;
994
995 msg = (char *) re_comp (regex);
996 if (msg)
997 error (msg);
998
999 if (current_source_symtab == 0)
1000 select_source_symtab (0);
1001
1002 /* Search from last_line_listed+1 in current_source_symtab */
1003
1004 desc = open_source_file (current_source_symtab);
1005 if (desc < 0)
1006 perror_with_name (current_source_symtab->filename);
1007
1008 if (current_source_symtab->line_charpos == 0)
1009 find_source_lines (current_source_symtab, desc);
1010
1011 if (line < 1 || line > current_source_symtab->nlines)
1012 {
1013 close (desc);
1014 error ("Expression not found");
1015 }
1016
1017 if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
1018 {
1019 close (desc);
1020 perror_with_name (current_source_symtab->filename);
1021 }
1022
1023 stream = fdopen (desc, "r");
1024 clearerr (stream);
1025 while (1) {
1026 char buf[4096]; /* Should be reasonable??? */
1027 register char *p = buf;
1028
1029 c = fgetc (stream);
1030 if (c == EOF)
1031 break;
1032 do {
1033 *p++ = c;
1034 } while (c != '\n' && (c = fgetc (stream)) >= 0);
1035
1036 /* we now have a source line in buf, null terminate and match */
1037 *p = 0;
1038 if (re_exec (buf) > 0)
1039 {
1040 /* Match! */
1041 fclose (stream);
1042 print_source_lines (current_source_symtab,
1043 line, line+1, 0);
1044 current_source_line = max (line - lines_to_list () / 2, 1);
1045 return;
1046 }
1047 line++;
1048 }
1049
1050 printf ("Expression not found\n");
1051 fclose (stream);
1052}
1053
1054static void
1055reverse_search_command (regex, from_tty)
1056 char *regex;
1057 int from_tty;
1058{
1059 register int c;
1060 register int desc;
1061 register FILE *stream;
1062 int line = last_line_listed - 1;
1063 char *msg;
1064
1065 msg = (char *) re_comp (regex);
1066 if (msg)
1067 error (msg);
1068
1069 if (current_source_symtab == 0)
1070 select_source_symtab (0);
1071
1072 /* Search from last_line_listed-1 in current_source_symtab */
1073
1074 desc = open_source_file (current_source_symtab);
1075 if (desc < 0)
1076 perror_with_name (current_source_symtab->filename);
1077
1078 if (current_source_symtab->line_charpos == 0)
1079 find_source_lines (current_source_symtab, desc);
1080
1081 if (line < 1 || line > current_source_symtab->nlines)
1082 {
1083 close (desc);
1084 error ("Expression not found");
1085 }
1086
1087 if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
1088 {
1089 close (desc);
1090 perror_with_name (current_source_symtab->filename);
1091 }
1092
1093 stream = fdopen (desc, "r");
1094 clearerr (stream);
1095 while (line > 1)
1096 {
1097 char buf[4096]; /* Should be reasonable??? */
1098 register char *p = buf;
1099
1100 c = fgetc (stream);
1101 if (c == EOF)
1102 break;
1103 do {
1104 *p++ = c;
1105 } while (c != '\n' && (c = fgetc (stream)) >= 0);
1106
1107 /* We now have a source line in buf; null terminate and match. */
1108 *p = 0;
1109 if (re_exec (buf) > 0)
1110 {
1111 /* Match! */
1112 fclose (stream);
1113 print_source_lines (current_source_symtab,
1114 line, line+1, 0);
1115 current_source_line = max (line - lines_to_list () / 2, 1);
1116 return;
1117 }
1118 line--;
1119 if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
1120 {
1121 fclose (stream);
1122 perror_with_name (current_source_symtab->filename);
1123 }
1124 }
1125
1126 printf ("Expression not found\n");
1127 fclose (stream);
1128 return;
1129}
1130\f
1131void
1132_initialize_source ()
1133{
1134 current_source_symtab = 0;
1135 init_source_path ();
1136
1137 add_com ("directory", class_files, directory_command,
1138 "Add directory DIR to beginning of search path for source files.\n\
1139Forget cached info on source file locations and line positions.\n\
1140DIR can also be $cwd for the current working directory, or $cdir for the\n\
1141directory in which the source file was compiled into object code.\n\
1142With no argument, reset the search path to $cdir:$cwd, the default.");
1143
1144 add_info ("directories", directories_info,
1145 "Current search path for finding source files.\n\
1146$cwd in the path means the current working directory.\n\
1147$cdir in the path means the compilation directory of the source file.");
1148
1149 add_info ("source", source_info,
1150 "Information about the current source file.");
1151
1152 add_info ("line", line_info,
1153 "Core addresses of the code for a source line.\n\
1154Line can be specified as\n\
1155 LINENUM, to list around that line in current file,\n\
1156 FILE:LINENUM, to list around that line in that file,\n\
1157 FUNCTION, to list around beginning of that function,\n\
1158 FILE:FUNCTION, to distinguish among like-named static functions.\n\
1159Default is to describe the last source line that was listed.\n\n\
1160This sets the default address for \"x\" to the line's first instruction\n\
1161so that \"x/i\" suffices to start examining the machine code.\n\
1162The address is also stored as the value of \"$_\".");
1163
1164 add_com ("forward-search", class_files, forward_search_command,
1165 "Search for regular expression (see regex(3)) from last line listed.");
1166 add_com_alias ("search", "forward-search", class_files, 0);
1167
1168 add_com ("reverse-search", class_files, reverse_search_command,
1169 "Search backward for regular expression (see regex(3)) from last line listed.");
1170
1171 add_com ("list", class_files, list_command,
1172 "List specified function or line.\n\
1173With no argument, lists ten more lines after or around previous listing.\n\
1174\"list -\" lists the ten lines before a previous ten-line listing.\n\
1175One argument specifies a line, and ten lines are listed around that line.\n\
1176Two arguments with comma between specify starting and ending lines to list.\n\
1177Lines can be specified in these ways:\n\
1178 LINENUM, to list around that line in current file,\n\
1179 FILE:LINENUM, to list around that line in that file,\n\
1180 FUNCTION, to list around beginning of that function,\n\
1181 FILE:FUNCTION, to distinguish among like-named static functions.\n\
1182 *ADDRESS, to list around the line containing that address.\n\
1183With two args if one is empty it stands for ten lines away from the other arg.");
1184 add_com_alias ("l", "list", class_files, 0);
1185}
1186
This page took 0.064835 seconds and 4 git commands to generate.