1 /* List lines of source files for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
4 GDB is distributed in the hope that it will be useful, but WITHOUT ANY
5 WARRANTY. No author or distributor accepts responsibility to anyone
6 for the consequences of using it or for whether it serves any
7 particular purpose or works at all, unless he says so in writing.
8 Refer to the GDB General Public License for full details.
10 Everyone is granted permission to copy, modify and redistribute GDB,
11 but only under the conditions described in the GDB General Public
12 License. A copy of this license is supposed to have been given to you
13 along with GDB so you can know your rights and responsibilities. It
14 should be in a file named COPYING. Among other things, the copyright
15 notice and this notice must be preserved on all copies.
17 In other words, go ahead and share GDB, but don't try to stop
18 anyone else from sharing it farther. Help stamp out software hoarding!
22 #include <sys/types.h>
23 #include <sys/param.h>
27 #include "initialize.h"
30 /* Path of directories to search for source files.
31 Same format as the PATH environment variable's value. */
33 static char *source_path;
35 /* Symtab of default file for listing lines of. */
37 struct symtab *current_source_symtab;
39 /* Default next line to list. */
41 int current_source_line;
43 /* Line for "info line" to work on if no line specified. */
45 static int line_info_default_line;
47 /* First line number listed by last listing command. */
49 static int first_line_listed;
53 /* Set the source file default for the "list" command,
54 specifying a symtab. */
57 select_source_symtab (s)
58 register struct symtab *s;
62 struct symtab_and_line sal;
64 /* Make the default place to list be the function `main'
66 if (lookup_symbol ("main", 0, VAR_NAMESPACE))
68 sal = decode_line_spec ("main", 1);
69 current_source_symtab = sal.symtab;
70 current_source_line = sal.line - 9;
74 /* If there is no `main', use the last symtab in the list,
75 which is actually the first found in the file's symbol table.
76 But ignore .h files. */
79 char *name = s->filename;
80 int len = strlen (name);
81 if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
82 current_source_symtab = s;
86 current_source_line = 1;
93 printf ("Source directories searched: %s\n", source_path);
99 register struct symtab *s;
101 if (getwd (wd) == NULL)
102 perror_with_name ("getwd");
104 source_path = savestring (wd, strlen (wd));
106 /* Forget what we learned about line positions in source files;
107 must check again now since files may be found in
108 a different directory now. */
109 for (s = symtab_list; s; s = s->next)
110 if (s->line_charpos != 0)
112 free (s->line_charpos);
118 directory_command (dirname, from_tty)
122 char *old = source_path;
125 if (getwd (wd) == NULL)
126 perror_with_name ("getwd");
130 if (query ("Reinitialize source path to %s? ", wd))
139 register int len = strlen (dirname);
141 extern char *index ();
143 if (index (dirname, ':'))
144 error ("Please add one directory at a time to the source path.");
145 if (dirname[len - 1] == '/')
146 /* Sigh. "foo/" => "foo" */
147 dirname[--len] == '\0';
149 while (dirname[len - 1] == '.')
153 /* "." => getwd () */
157 else if (dirname[len - 2] == '/')
162 dirname[--len] = '\0';
167 /* "...foo/." => "...foo" */
168 dirname[len -= 2] = '\0';
175 if (dirname[0] != '/')
176 dirname = concat (wd, "/", dirname);
178 dirname = savestring (dirname, len);
179 make_cleanup (free, dirname);
181 if (stat (dirname, &st) < 0)
182 perror_with_name (dirname);
183 if ((st.st_mode & S_IFMT) != S_IFDIR)
184 error ("%s is not a directory.", dirname);
187 len = strlen (dirname);
191 if (!strncmp (tem, dirname, len)
192 && (tem[len] == '\0' || tem[len] == ':'))
194 printf ("\"%s\" is already in the source path.\n",
198 tem = index (tem, ':');
203 source_path = concat (old, ":", dirname);
213 /* Open a file named STRING, searching path PATH (dir names sep by colons)
214 using mode MODE and protection bits PROT in the calls to open.
215 If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
216 (ie pretend the first element of PATH is ".")
217 If FILENAMED_OPENED is non-null, set it to a newly allocated string naming
218 the actual file opened (this string will always start with a "/"
220 If a file is found, return the descriptor.
221 Otherwise, return -1, with errno set for the last name we tried to open. */
223 /* >>>> This should only allow files of certain types,
224 >>>> eg executable, non-directory */
226 openp (path, try_cwd_first, string, mode, prot, filename_opened)
232 char **filename_opened;
235 register char *filename;
236 register char *p, *p1;
240 while (string[0] == '.' && string[1] == '/')
243 if (try_cwd_first || string[0] == '/')
246 fd = open (filename, mode, prot);
247 if (fd >= 0 || string[0] == '/')
251 filename = (char *) alloca (strlen (path) + strlen (string) + 2);
253 for (p = path; p; p = p1 ? p1 + 1 : 0)
255 p1 = (char *) index (p, ':');
261 strncpy (filename, p, len);
263 strcat (filename, "/");
264 strcat (filename, string);
266 fd = open (filename, mode, prot);
273 *filename_opened = (char *) 0;
274 else if (filename[0] == '/')
275 *filename_opened = savestring (filename, strlen (filename));
278 char dirname[MAXPATHLEN];
279 if (getwd (dirname) == NULL)
280 perror_with_name ("getwd");
281 *filename_opened = concat (dirname, "/", filename);
287 /* Create and initialize the table S->line_charpos that records
288 the positions of the lines in the source file, which is assumed
289 to be open on descriptor DESC.
290 All set S->nlines to the number of such lines. */
293 find_source_lines (s, desc)
298 register char *data, *p, *end;
300 int lines_allocated = 1000;
301 int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
302 extern int exec_mtime;
305 if (get_exec_file () != 0 && exec_mtime < st.st_mtime)
306 printf ("Source file is more recent than executable.\n");
308 data = (char *) alloca (st.st_size);
309 myread (desc, data, st.st_size);
310 end = data + st.st_size;
318 if (nlines == lines_allocated)
319 line_charpos = (int *) xrealloc (line_charpos,
320 sizeof (int) * (lines_allocated *= 2));
321 line_charpos[nlines++] = p - data;
325 s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
328 /* Return the character position of a line LINE in symtab S.
329 Return 0 if anything is invalid. */
332 source_line_charpos (s, line)
337 if (!s->line_charpos || line <= 0) return 0;
338 if (line > s->nlines)
340 return s->line_charpos[line - 1];
343 /* Return the line number of character position POS in symtab S. */
346 source_charpos_line (s, chr)
347 register struct symtab *s;
350 register int line = 0;
353 if (s == 0 || s->line_charpos == 0) return 0;
354 lnp = s->line_charpos;
355 /* Files are usually short, so sequential search is Ok */
356 while (line < s->nlines && *lnp <= chr)
361 if (line >= s->nlines)
366 /* Get full pathname and line number positions for a symtab.
367 Return nonzero if line numbers may have changed.
368 Set *FULLNAME to actual name of the file as found by `openp',
369 or to 0 if the file is not found. */
372 get_filename_and_charpos (s, line, fullname)
377 register int desc, linenums_changed = 0;
379 desc = openp (source_path, 0, s->filename, O_RDONLY, 0, fullname);
385 if (s->line_charpos == 0) linenums_changed = 1;
386 if (linenums_changed) find_source_lines (s, desc);
388 return linenums_changed;
391 /* Print source lines from the file of symtab S,
392 starting with line number LINE and stopping before line number STOPLINE. */
395 print_source_lines (s, line, stopline)
401 register FILE *stream;
402 int nlines = stopline - line;
404 desc = openp (source_path, 0, s->filename, O_RDONLY, 0, (char **) 0);
406 perror_with_name (s->filename);
408 if (s->line_charpos == 0)
409 find_source_lines (s, desc);
411 if (line < 1 || line >= s->nlines)
414 error ("Line number out of range; %s has %d lines.",
415 s->filename, s->nlines);
418 if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
421 perror_with_name (s->filename);
424 current_source_symtab = s;
425 current_source_line = line;
426 first_line_listed = line;
428 stream = fdopen (desc, "r");
435 line_info_default_line = current_source_line;
436 printf ("%d\t", current_source_line++);
439 if (c < 040 && c != '\t' && c != '\n')
442 fputc (c + 0100, stdout);
448 } while (c != '\n' && (c = fgetc (stream)) >= 0);
455 list_command (arg, from_tty)
459 struct symtab_and_line sal, sal_end;
468 if (symtab_list == 0)
469 error ("Listing source lines requires symbols.");
471 /* "l" or "l +" lists next ten lines. */
473 if (arg == 0 || !strcmp (arg, "+"))
475 if (current_source_symtab == 0)
476 error ("No default source file yet. Do \"help list\".");
477 print_source_lines (current_source_symtab, current_source_line,
478 current_source_line + 10);
482 /* "l -" lists previous ten lines, the ones before the ten just listed. */
483 if (!strcmp (arg, "-"))
485 if (current_source_symtab == 0)
486 error ("No default source file yet. Do \"help list\".");
487 print_source_lines (current_source_symtab,
488 max (first_line_listed - 10, 1),
493 /* Now if there is only one argument, decode it in SAL
495 If there are two arguments, decode them in SAL and SAL_END
496 and clear NO_END; however, if one of the arguments is blank,
497 set DUMMY_BEG or DUMMY_END to record that fact. */
503 sal = decode_line_1 (&arg1, 0, 0, 0);
505 /* Record whether the BEG arg is all digits. */
507 for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
508 linenum_beg = (p == arg1);
510 while (*arg1 == ' ' || *arg1 == '\t')
516 while (*arg1 == ' ' || *arg1 == '\t')
521 sal_end = decode_line_1 (&arg1, 0, 0, 0);
523 sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
527 error ("Junk at end of line specification.");
529 if (!no_end && !dummy_beg && !dummy_end
530 && sal.symtab != sal_end.symtab)
531 error ("Specified start and end are in different files.");
532 if (dummy_beg && dummy_end)
533 error ("Two empty args do not say what lines to list.");
535 /* if line was specified by address,
536 first print exactly which line, and which file.
537 In this case, sal.symtab == 0 means address is outside
538 of all known source files, not that user failed to give a filename. */
542 error ("No source file for address 0x%x.", sal.pc);
543 sym = find_pc_function (sal.pc);
545 printf ("0x%x is in %s (%s, line %d).\n",
546 sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
548 printf ("0x%x is in %s, line %d.\n",
549 sal.pc, sal.symtab->filename, sal.line);
552 /* If line was not specified by just a line number,
553 and it does not imply a symtab, it must be an undebuggable symbol
554 which means no source code. */
556 if (! linenum_beg && sal.symtab == 0)
557 error ("No line number known for %s.", arg);
559 /* If this command is repeated with RET,
560 turn it into the no-arg variant. */
565 if (dummy_beg && sal_end.symtab == 0)
566 error ("No default source file yet. Do \"help list\".");
568 print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1),
570 else if (sal.symtab == 0)
571 error ("No default source file yet. Do \"help list\".");
573 print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5);
575 print_source_lines (sal.symtab, sal.line,
576 dummy_end ? sal.line + 10 : sal_end.line + 1);
579 /* Print info on range of pc's in a specified line. */
582 line_info (arg, from_tty)
586 struct symtab_and_line sal;
587 int start_pc, end_pc;
591 sal.symtab = current_source_symtab;
592 sal.line = line_info_default_line;
596 sal = decode_line_spec (arg);
598 /* If this command is repeated with RET,
599 turn it into the no-arg variant. */
606 error ("No source file specified.");
608 && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
610 if (start_pc == end_pc)
611 printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n",
612 sal.line, sal.symtab->filename, start_pc);
614 printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n",
615 sal.line, sal.symtab->filename, start_pc, end_pc);
616 /* x/i should display this line's code. */
617 set_next_address (start_pc);
618 /* Repeating "info line" should do the following line. */
619 line_info_default_line = sal.line + 1;
622 printf ("Line number %d is out of range for \"%s\".\n",
623 sal.line, sal.symtab->filename);
629 current_source_symtab = 0;
632 add_com ("directory", class_files, directory_command,
633 "Add directory DIR to end of search path for source files.\n\
634 With no argument, reset the search path to just the working directory\n\
635 and forget cached info on line positions in source files.");
637 add_info ("directories", directories_info,
638 "Current search path for finding source files.");
640 add_info ("line", line_info,
641 "Core addresses of the code for a source line.\n\
642 Line can be specified as\n\
643 LINENUM, to list around that line in current file,\n\
644 FILE:LINENUM, to list around that line in that file,\n\
645 FUNCTION, to list around beginning of that function,\n\
646 FILE:FUNCTION, to distinguish among like-named static functions.\n\
647 Default is to describe the last source line that was listed.\n\n\
648 This sets the default address for \"x\" to the line's first instruction\n\
649 so that \"x/i\" suffices to start examining the machine code.\n\
650 The address is also stored as the value of \"$_\".");
652 add_com ("list", class_files, list_command,
653 "List specified function or line.\n\
654 With no argument, lists ten more lines after or around previous listing.\n\
655 \"list -\" lists the ten lines before a previous ten-line listing.\n\
656 One argument specifies a line, and ten lines are listed around that line.\n\
657 Two arguments with comma between specify starting and ending lines to list.\n\
658 Lines can be specified in these ways:\n\
659 LINENUM, to list around that line in current file,\n\
660 FILE:LINENUM, to list around that line in that file,\n\
661 FUNCTION, to list around beginning of that function,\n\
662 FILE:FUNCTION, to distinguish among like-named static functions.\n\
663 *ADDRESS, to list around the line containing that address.\n\
664 With two args if one is empty it stands for ten lines away from the other arg.");