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