6ad887a654dd514ca65dde9113d17883b5ac0541
[deliverable/binutils-gdb.git] / gdb / source.c
1 /* List lines of source files for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 GDB is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 GDB is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GDB; see the file COPYING. If not, write to
18 the 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 "gdbcmd.h"
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
38 extern char *strstr();
39
40 extern void set_next_address ();
41
42 void mod_path ();
43
44 /* Path of directories to search for source files.
45 Same format as the PATH environment variable's value. */
46
47 char *source_path;
48
49 /* Symtab of default file for listing lines of. */
50
51 struct symtab *current_source_symtab;
52
53 /* Default next line to list. */
54
55 int 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
60 static int last_line_listed;
61
62 /* First line number listed by last listing command. */
63
64 static 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
75 void
76 select_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
140 static void
141 show_directories ()
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
151 void
152 forget_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
171 void
172 init_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
180 void
181 directory_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)
198 show_directories ();
199 forget_cached_source_info ();
200 }
201
202 /* Add zero or more directories to the front of an arbitrary path. */
203
204 void
205 mod_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
348 static void
349 source_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 */
392 int
393 openp (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. */
482 int
483 open_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
528 static void
529 find_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
578 int
579 source_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
592 int
593 source_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
618 int
619 get_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
649 int
650 identify_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
673 void
674 print_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 */
748 static void
749 ambiguous_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
760 static void
761 list_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),
914 sal.line + (lines_to_list() / 2), 0);
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
925 static void
926 line_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
985 static void
986 forward_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
1055 static void
1056 reverse_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
1132 void
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\
1140 Forget cached info on source file locations and line positions.\n\
1141 DIR can also be $cwd for the current working directory, or $cdir for the\n\
1142 directory in which the source file was compiled into object code.\n\
1143 With no argument, reset the search path to $cdir:$cwd, the default.");
1144
1145 add_cmd ("directories", no_class, show_directories,
1146 "Current search path for finding source files.\n\
1147 $cwd in the path means the current working directory.\n\
1148 $cdir in the path means the compilation directory of the source file.",
1149 &showlist);
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\
1156 Line 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\
1161 Default is to describe the last source line that was listed.\n\n\
1162 This sets the default address for \"x\" to the line's first instruction\n\
1163 so that \"x/i\" suffices to start examining the machine code.\n\
1164 The 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\
1175 With 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\
1177 One argument specifies a line, and ten lines are listed around that line.\n\
1178 Two arguments with comma between specify starting and ending lines to list.\n\
1179 Lines 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\
1185 With 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.072047 seconds and 3 git commands to generate.