gdb-2.4+.aux.coff
[external/binutils.git] / gdb / source.c
1 /* List lines of source files for GDB, the GNU debugger.
2    Copyright (C) 1986, 1987 Free Software Foundation, Inc.
3
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.
9
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.
16
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!
19 */
20
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/param.h>
24 #include <sys/stat.h>
25 #include <sys/file.h>
26 #include "defs.h"
27 #include "initialize.h"
28 #include "symtab.h"
29
30 /* Path of directories to search for source files.
31    Same format as the PATH environment variable's value.  */
32
33 static char *source_path;
34
35 /* Symtab of default file for listing lines of.  */
36
37 struct symtab *current_source_symtab;
38
39 /* Default next line to list.  */
40
41 int current_source_line;
42
43 /* Line for "info line" to work on if no line specified.  */
44
45 static int line_info_default_line;
46
47 /* First line number listed by last listing command.  */
48
49 static int first_line_listed;
50
51 START_FILE
52 \f
53 /* Set the source file default for the "list" command,
54    specifying a symtab.  */
55
56 void
57 select_source_symtab (s)
58      register struct symtab *s;
59 {
60   if (s)
61     {
62       struct symtab_and_line sal;
63
64       /* Make the default place to list be the function `main'
65          if one exists.  */
66       if (lookup_symbol ("main", 0, VAR_NAMESPACE))
67         {
68           sal = decode_line_spec ("main", 1);
69           current_source_symtab = sal.symtab;
70           current_source_line = sal.line - 9;
71           return;
72         }
73
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.  */
77       do
78         {
79           char *name = s->filename;
80           int len = strlen (name);
81           if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
82             current_source_symtab = s;
83           s = s->next;
84         }
85       while (s);
86       current_source_line = 1;
87     }
88 }
89 \f
90 static void
91 directories_info ()
92 {
93   printf ("Source directories searched: %s\n", source_path);
94 }
95
96 static void
97 init_source_path ()
98 {
99   register struct symtab *s;
100   char wd[MAXPATHLEN];
101   if (getwd (wd) == NULL)
102     perror_with_name ("getwd");
103
104   source_path = savestring (wd, strlen (wd));
105
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)
111       {
112         free (s->line_charpos);
113         s->line_charpos = 0;
114       }
115 }
116
117 void
118 directory_command (dirname, from_tty)
119      char *dirname;
120      int from_tty;
121 {
122   char *old = source_path;
123
124   char wd[MAXPATHLEN];
125   if (getwd (wd) == NULL)
126     perror_with_name ("getwd");
127
128   if (dirname == 0)
129     {
130       if (query ("Reinitialize source path to %s? ", wd))
131         {
132           init_source_path ();
133           free (old);
134         }
135     }
136   else
137     {
138       struct stat st;
139       register int len = strlen (dirname);
140       register char *tem;
141       extern char *index ();
142
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';
148
149       while (dirname[len - 1] == '.')
150         {
151           if (len == 1)
152             {
153               /* "." => getwd () */
154               dirname = wd;
155               goto append;
156             }
157           else if (dirname[len - 2] == '/')
158             {
159               if (len == 2)
160                 {
161                   /* "/." => "/" */
162                   dirname[--len] = '\0';
163                   goto append;
164                 }
165               else
166                 {
167                   /* "...foo/." => "...foo" */
168                   dirname[len -= 2] = '\0';
169                   continue;
170                 }
171             }
172           break;
173         }
174
175       if (dirname[0] != '/')
176         dirname = concat (wd, "/", dirname);
177       else
178         dirname = savestring (dirname, len);
179       make_cleanup (free, dirname);
180
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);
185
186     append:
187       len = strlen (dirname);
188       tem = source_path;
189       while (1)
190         {
191           if (!strncmp (tem, dirname, len)
192               && (tem[len] == '\0' || tem[len] == ':'))
193             {
194               printf ("\"%s\" is already in the source path.\n",
195                       dirname);
196               break;
197             }
198           tem = index (tem, ':');
199           if (tem)
200             tem++;
201           else
202             {
203               source_path = concat (old, ":", dirname);
204               free (old);
205               break;
206             }
207         }
208       if (from_tty)
209         directories_info ();
210     }
211 }
212 \f
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 "/"
219
220    If a file is found, return the descriptor.
221    Otherwise, return -1, with errno set for the last name we tried to open.  */
222
223 /*  >>>> This should only allow files of certain types,
224     >>>>  eg executable, non-directory */
225 int
226 openp (path, try_cwd_first, string, mode, prot, filename_opened)
227      char *path;
228      int try_cwd_first;
229      char *string;
230      int mode;
231      int prot;
232      char **filename_opened;
233 {
234   register int fd;
235   register char *filename;
236   register char *p, *p1;
237   register int len;
238
239   /* ./foo => foo */
240   while (string[0] == '.' && string[1] == '/')
241     string += 2;
242
243   if (try_cwd_first || string[0] == '/')
244     {
245       filename = string;
246       fd = open (filename, mode, prot);
247       if (fd >= 0 || string[0] == '/')
248         goto done;
249     }
250
251   filename = (char *) alloca (strlen (path) + strlen (string) + 2);
252   fd = -1;
253   for (p = path; p; p = p1 ? p1 + 1 : 0)
254     {
255       p1 = (char *) index (p, ':');
256       if (p1)
257         len = p1 - p;
258       else
259         len = strlen (p);
260
261       strncpy (filename, p, len);
262       filename[len] = 0;
263       strcat (filename, "/");
264       strcat (filename, string);
265
266       fd = open (filename, mode, prot);
267       if (fd >= 0) break;
268     }
269
270  done:
271   if (filename_opened)
272     if (fd < 0)
273       *filename_opened = (char *) 0;
274     else if (filename[0] == '/')
275       *filename_opened = savestring (filename, strlen (filename));
276     else
277       {
278         char dirname[MAXPATHLEN];
279         if (getwd (dirname) == NULL)
280           perror_with_name ("getwd");
281         *filename_opened = concat (dirname, "/", filename);
282       }
283
284   return fd;
285 }
286 \f
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.  */
291
292 static void
293 find_source_lines (s, desc)
294      struct symtab *s;
295      int desc;
296 {
297   struct stat st;
298   register char *data, *p, *end;
299   int nlines = 0;
300   int lines_allocated = 1000;
301   int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
302   extern int exec_mtime;
303
304   fstat (desc, &st);
305   if (get_exec_file () != 0 && exec_mtime < st.st_mtime)
306     printf ("Source file is more recent than executable.\n");
307
308   data = (char *) alloca (st.st_size);
309   myread (desc, data, st.st_size);
310   end = data + st.st_size;
311   p = data;
312   line_charpos[0] = 0;
313   nlines = 1;
314   while (p != end)
315     {
316       if (*p++ == '\n')
317         {
318           if (nlines == lines_allocated)
319             line_charpos = (int *) xrealloc (line_charpos,
320                                              sizeof (int) * (lines_allocated *= 2));
321           line_charpos[nlines++] = p - data;
322         }
323     }
324   s->nlines = nlines;
325   s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
326 }
327
328 /* Return the character position of a line LINE in symtab S.
329    Return 0 if anything is invalid.  */
330
331 int
332 source_line_charpos (s, line)
333      struct symtab *s;
334      int line;
335 {
336   if (!s) return 0;
337   if (!s->line_charpos || line <= 0) return 0;
338   if (line > s->nlines)
339     line = s->nlines;
340   return s->line_charpos[line - 1];
341 }
342
343 /* Return the line number of character position POS in symtab S.  */
344
345 int
346 source_charpos_line (s, chr)
347     register struct symtab *s;
348     register int chr;
349 {
350   register int line = 0;
351   register int *lnp;
352     
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)
357     {
358       line++;
359       lnp++;
360     }
361   if (line >= s->nlines)
362     line = s->nlines;
363   return line;
364 }
365 \f
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.  */
370
371 int
372 get_filename_and_charpos (s, line, fullname)
373      struct symtab *s;
374      int line;
375      char **fullname;
376 {
377   register int desc, linenums_changed = 0;
378   
379   desc = openp (source_path, 0, s->filename, O_RDONLY, 0, fullname);
380   if (desc < 0)
381     {
382       *fullname = NULL;
383       return 0;
384     }  
385   if (s->line_charpos == 0) linenums_changed = 1;
386   if (linenums_changed) find_source_lines (s, desc);
387   close (desc);
388   return linenums_changed;
389 }
390 \f
391 /* Print source lines from the file of symtab S,
392    starting with line number LINE and stopping before line number STOPLINE.  */
393
394 void
395 print_source_lines (s, line, stopline)
396      struct symtab *s;
397      int line, stopline;
398 {
399   register int c;
400   register int desc;
401   register FILE *stream;
402   int nlines = stopline - line;
403
404   desc = openp (source_path, 0, s->filename, O_RDONLY, 0, (char **) 0);
405   if (desc < 0)
406     perror_with_name (s->filename);
407
408   if (s->line_charpos == 0)
409     find_source_lines (s, desc);
410
411   if (line < 1 || line >= s->nlines)
412     {
413       close (desc);
414       error ("Line number out of range; %s has %d lines.",
415              s->filename, s->nlines);
416     }
417
418   if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
419     {
420       close (desc);
421       perror_with_name (s->filename);
422     }
423
424   current_source_symtab = s;
425   current_source_line = line;
426   first_line_listed = line;
427   
428   stream = fdopen (desc, "r");
429   clearerr (stream);
430
431   while (nlines-- > 0)
432     {
433       c = fgetc (stream);
434       if (c == EOF) break;
435       line_info_default_line = current_source_line;
436       printf ("%d\t", current_source_line++);
437       do
438         {
439           if (c < 040 && c != '\t' && c != '\n')
440             {
441               fputc ('^', stdout);
442               fputc (c + 0100, stdout);
443             }
444           else if (c == 0177)
445             printf ("^?");
446           else
447             fputc (c, stdout);
448         } while (c != '\n' && (c = fgetc (stream)) >= 0);
449     }
450
451   fclose (stream);
452 }
453 \f
454 static void
455 list_command (arg, from_tty)
456      char *arg;
457      int from_tty;
458 {
459   struct symtab_and_line sal, sal_end;
460   struct symbol *sym;
461   char *arg1;
462   int no_end = 1;
463   int dummy_end = 0;
464   int dummy_beg = 0;
465   int linenum_beg = 0;
466   char *p;
467
468   if (symtab_list == 0)
469     error ("Listing source lines requires symbols.");
470
471   /* "l" or "l +" lists next ten lines.  */
472
473   if (arg == 0 || !strcmp (arg, "+"))
474     {
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);
479       return;
480     }
481
482   /* "l -" lists previous ten lines, the ones before the ten just listed.  */
483   if (!strcmp (arg, "-"))
484     {
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),
489                           first_line_listed);
490       return;
491     }
492
493   /* Now if there is only one argument, decode it in SAL
494      and set NO_END.
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.  */
498
499   arg1 = arg;
500   if (*arg1 == ',')
501     dummy_beg = 1;
502   else
503     sal = decode_line_1 (&arg1, 0, 0, 0);
504
505   /* Record whether the BEG arg is all digits.  */
506
507   for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
508   linenum_beg = (p == arg1);
509
510   while (*arg1 == ' ' || *arg1 == '\t')
511     arg1++;
512   if (*arg1 == ',')
513     {
514       no_end = 0;
515       arg1++;
516       while (*arg1 == ' ' || *arg1 == '\t')
517         arg1++;
518       if (*arg1 == 0)
519         dummy_end = 1;
520       else if (dummy_beg)
521         sal_end = decode_line_1 (&arg1, 0, 0, 0);
522       else
523         sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
524     }
525
526   if (*arg1)
527     error ("Junk at end of line specification.");
528
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.");
534  
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.  */
539   if (*arg == '*')
540     {
541       if (sal.symtab == 0)
542         error ("No source file for address 0x%x.", sal.pc);
543       sym = find_pc_function (sal.pc);
544       if (sym)
545         printf ("0x%x is in %s (%s, line %d).\n",
546                 sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
547       else
548         printf ("0x%x is in %s, line %d.\n",
549                 sal.pc, sal.symtab->filename, sal.line);
550     }
551
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.  */
555
556   if (! linenum_beg && sal.symtab == 0)
557     error ("No line number known for %s.", arg);
558
559   /* If this command is repeated with RET,
560      turn it into the no-arg variant.  */
561
562   if (from_tty)
563     *arg = 0;
564
565   if (dummy_beg && sal_end.symtab == 0)
566     error ("No default source file yet.  Do \"help list\".");
567   if (dummy_beg)
568     print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1),
569                         sal_end.line + 1);
570   else if (sal.symtab == 0)
571     error ("No default source file yet.  Do \"help list\".");
572   else if (no_end)
573     print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5);
574   else
575     print_source_lines (sal.symtab, sal.line,
576                         dummy_end ? sal.line + 10 : sal_end.line + 1);
577 }
578 \f
579 /* Print info on range of pc's in a specified line.  */
580
581 static void
582 line_info (arg, from_tty)
583      char *arg;
584      int from_tty;
585 {
586   struct symtab_and_line sal;
587   int start_pc, end_pc;
588
589   if (arg == 0)
590     {
591       sal.symtab = current_source_symtab;
592       sal.line = line_info_default_line;
593     }
594   else
595     {
596       sal = decode_line_spec (arg);
597
598       /* If this command is repeated with RET,
599          turn it into the no-arg variant.  */
600
601       if (from_tty)
602         *arg = 0;
603     }
604
605   if (sal.symtab == 0)
606     error ("No source file specified.");
607   if (sal.line > 0
608       && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
609     {
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);
613       else
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;
620     }
621   else
622     printf ("Line number %d is out of range for \"%s\".\n",
623             sal.line, sal.symtab->filename);
624 }
625 \f
626 static
627 initialize ()
628 {
629   current_source_symtab = 0;
630   init_source_path ();
631
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.");
636
637   add_info ("directories", directories_info,
638             "Current search path for finding source files.");
639
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 \"$_\".");
651
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.");
665 }
666
667 END_FILE