gdb-3.1
[binutils-gdb.git] / gdb / source.c
1 /* List lines of source files for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987, 1988 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 "defs.h"
22 #include "symtab.h"
23 #include "param.h"
24
25 #ifdef USG
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #endif
29
30 #include <stdio.h>
31 #include <sys/param.h>
32 #include <sys/stat.h>
33 #include <sys/file.h>
34
35 /* Path of directories to search for source files.
36 Same format as the PATH environment variable's value. */
37
38 static char *source_path;
39
40 /* Symtab of default file for listing lines of. */
41
42 struct symtab *current_source_symtab;
43
44 /* Default next line to list. */
45
46 int current_source_line;
47
48 /* Line number of last line printed. Default for various commands.
49 current_source_line is usually, but not always, the same as this. */
50
51 static int last_line_listed;
52
53 /* First line number listed by last listing command. */
54
55 static int first_line_listed;
56
57 \f
58 struct symtab *psymtab_to_symtab ();
59
60 /* Set the source file default for the "list" command,
61 specifying a symtab. */
62
63 void
64 select_source_symtab (s)
65 register struct symtab *s;
66 {
67 struct symtabs_and_lines sals;
68 struct symtab_and_line sal;
69 struct partial_symtab *ps, *cs_pst;
70
71 /* Make the default place to list be the function `main'
72 if one exists. */
73 if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0))
74 {
75 sals = decode_line_spec ("main", 1);
76 sal = sals.sals[0];
77 free (sals.sals);
78 current_source_symtab = sal.symtab;
79 current_source_line = sal.line - 9;
80 return;
81 }
82
83 /* If there is no `main', use the last symtab in the list,
84 which is actually the first found in the file's symbol table.
85 But ignore .h files. */
86 if (s)
87 {
88 do
89 {
90 char *name = s->filename;
91 int len = strlen (name);
92 if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
93 current_source_symtab = s;
94 s = s->next;
95 }
96 while (s);
97 current_source_line = 1;
98 }
99 else
100 {
101 ps = partial_symtab_list;
102 while (ps)
103 {
104 char *name = ps->filename;
105 int len = strlen (name);
106 if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
107 cs_pst = ps;
108 ps = ps->next;
109 }
110 if (cs_pst)
111 current_source_symtab = psymtab_to_symtab (cs_pst);
112 else
113 current_source_symtab = 0;
114 current_source_line = 1;
115 }
116 }
117 \f
118 static void
119 directories_info ()
120 {
121 printf ("Source directories searched: %s\n", source_path);
122 }
123
124 void
125 init_source_path ()
126 {
127 register struct symtab *s;
128
129 source_path = savestring (current_directory, strlen (current_directory));
130
131 /* Forget what we learned about line positions in source files;
132 must check again now since files may be found in
133 a different directory now. */
134 for (s = symtab_list; s; s = s->next)
135 if (s->line_charpos != 0)
136 {
137 free (s->line_charpos);
138 s->line_charpos = 0;
139 }
140 }
141
142 void
143 directory_command (dirname, from_tty)
144 char *dirname;
145 int from_tty;
146 {
147 char *old = source_path;
148
149 if (dirname == 0)
150 {
151 if (query ("Reinitialize source path to %s? ", current_directory))
152 {
153 init_source_path ();
154 free (old);
155 }
156 }
157 else
158 {
159 struct stat st;
160 register int len = strlen (dirname);
161 register char *tem;
162 extern char *index ();
163
164 if (index (dirname, ':'))
165 error ("Please add one directory at a time to the source path.");
166 if (dirname[len - 1] == '/')
167 /* Sigh. "foo/" => "foo" */
168 dirname[--len] == '\0';
169
170 while (dirname[len - 1] == '.')
171 {
172 if (len == 1)
173 {
174 /* "." => getwd () */
175 dirname = current_directory;
176 goto append;
177 }
178 else if (dirname[len - 2] == '/')
179 {
180 if (len == 2)
181 {
182 /* "/." => "/" */
183 dirname[--len] = '\0';
184 goto append;
185 }
186 else
187 {
188 /* "...foo/." => "...foo" */
189 dirname[len -= 2] = '\0';
190 continue;
191 }
192 }
193 break;
194 }
195
196 if (dirname[0] != '/')
197 dirname = concat (current_directory, "/", dirname);
198 else
199 dirname = savestring (dirname, len);
200 make_cleanup (free, dirname);
201
202 if (stat (dirname, &st) < 0)
203 perror_with_name (dirname);
204 if ((st.st_mode & S_IFMT) != S_IFDIR)
205 error ("%s is not a directory.", dirname);
206
207 append:
208 len = strlen (dirname);
209 tem = source_path;
210 while (1)
211 {
212 if (!strncmp (tem, dirname, len)
213 && (tem[len] == '\0' || tem[len] == ':'))
214 {
215 printf ("\"%s\" is already in the source path.\n",
216 dirname);
217 break;
218 }
219 tem = index (tem, ':');
220 if (tem)
221 tem++;
222 else
223 {
224 source_path = concat (old, ":", dirname);
225 free (old);
226 break;
227 }
228 }
229 if (from_tty)
230 directories_info ();
231 }
232 }
233 \f
234 /* Open a file named STRING, searching path PATH (dir names sep by colons)
235 using mode MODE and protection bits PROT in the calls to open.
236 If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
237 (ie pretend the first element of PATH is ".")
238 If FILENAMED_OPENED is non-null, set it to a newly allocated string naming
239 the actual file opened (this string will always start with a "/"
240
241 If a file is found, return the descriptor.
242 Otherwise, return -1, with errno set for the last name we tried to open. */
243
244 /* >>>> This should only allow files of certain types,
245 >>>> eg executable, non-directory */
246 int
247 openp (path, try_cwd_first, string, mode, prot, filename_opened)
248 char *path;
249 int try_cwd_first;
250 char *string;
251 int mode;
252 int prot;
253 char **filename_opened;
254 {
255 register int fd;
256 register char *filename;
257 register char *p, *p1;
258 register int len;
259
260 /* ./foo => foo */
261 while (string[0] == '.' && string[1] == '/')
262 string += 2;
263
264 if (try_cwd_first || string[0] == '/')
265 {
266 filename = string;
267 fd = open (filename, mode, prot);
268 if (fd >= 0 || string[0] == '/')
269 goto done;
270 }
271
272 filename = (char *) alloca (strlen (path) + strlen (string) + 2);
273 fd = -1;
274 for (p = path; p; p = p1 ? p1 + 1 : 0)
275 {
276 p1 = (char *) index (p, ':');
277 if (p1)
278 len = p1 - p;
279 else
280 len = strlen (p);
281
282 strncpy (filename, p, len);
283 filename[len] = 0;
284 strcat (filename, "/");
285 strcat (filename, string);
286
287 fd = open (filename, mode, prot);
288 if (fd >= 0) break;
289 }
290
291 done:
292 if (filename_opened)
293 if (fd < 0)
294 *filename_opened = (char *) 0;
295 else if (filename[0] == '/')
296 *filename_opened = savestring (filename, strlen (filename));
297 else
298 {
299 *filename_opened = concat (current_directory, "/", filename);
300 }
301
302 return fd;
303 }
304 \f
305 /* Create and initialize the table S->line_charpos that records
306 the positions of the lines in the source file, which is assumed
307 to be open on descriptor DESC.
308 All set S->nlines to the number of such lines. */
309
310 static void
311 find_source_lines (s, desc)
312 struct symtab *s;
313 int desc;
314 {
315 struct stat st;
316 register char *data, *p, *end;
317 int nlines = 0;
318 int lines_allocated = 1000;
319 int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
320 extern int exec_mtime;
321
322 fstat (desc, &st);
323 if (get_exec_file (0) != 0 && exec_mtime < st.st_mtime)
324 printf ("Source file is more recent than executable.\n");
325
326 data = (char *) alloca (st.st_size);
327 myread (desc, data, st.st_size);
328 end = data + st.st_size;
329 p = data;
330 line_charpos[0] = 0;
331 nlines = 1;
332 while (p != end)
333 {
334 if (*p++ == '\n'
335 /* A newline at the end does not start a new line. */
336 && p != end)
337 {
338 if (nlines == lines_allocated)
339 {
340 lines_allocated *= 2;
341 line_charpos = (int *) xrealloc (line_charpos,
342 sizeof (int) * lines_allocated);
343 }
344 line_charpos[nlines++] = p - data;
345 }
346 }
347 s->nlines = nlines;
348 s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
349 }
350
351 /* Return the character position of a line LINE in symtab S.
352 Return 0 if anything is invalid. */
353
354 int
355 source_line_charpos (s, line)
356 struct symtab *s;
357 int line;
358 {
359 if (!s) return 0;
360 if (!s->line_charpos || line <= 0) return 0;
361 if (line > s->nlines)
362 line = s->nlines;
363 return s->line_charpos[line - 1];
364 }
365
366 /* Return the line number of character position POS in symtab S. */
367
368 int
369 source_charpos_line (s, chr)
370 register struct symtab *s;
371 register int chr;
372 {
373 register int line = 0;
374 register int *lnp;
375
376 if (s == 0 || s->line_charpos == 0) return 0;
377 lnp = s->line_charpos;
378 /* Files are usually short, so sequential search is Ok */
379 while (line < s->nlines && *lnp <= chr)
380 {
381 line++;
382 lnp++;
383 }
384 if (line >= s->nlines)
385 line = s->nlines;
386 return line;
387 }
388 \f
389 /* Get full pathname and line number positions for a symtab.
390 Return nonzero if line numbers may have changed.
391 Set *FULLNAME to actual name of the file as found by `openp',
392 or to 0 if the file is not found. */
393
394 int
395 get_filename_and_charpos (s, line, fullname)
396 struct symtab *s;
397 int line;
398 char **fullname;
399 {
400 register int desc, linenums_changed = 0;
401
402 desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
403 if (desc < 0)
404 {
405 if (fullname)
406 *fullname = NULL;
407 return 0;
408 }
409 if (fullname)
410 *fullname = s->fullname;
411 if (s->line_charpos == 0) linenums_changed = 1;
412 if (linenums_changed) find_source_lines (s, desc);
413 close (desc);
414 return linenums_changed;
415 }
416
417 /* Print text describing the full name of the source file S
418 and the line number LINE and its corresponding character position.
419 The text starts with two Ctrl-z so that the Emacs-GDB interface
420 can easily find it.
421
422 MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
423
424 Return 1 if successful, 0 if could not find the file. */
425
426 int
427 identify_source_line (s, line, mid_statement)
428 struct symtab *s;
429 int line;
430 int mid_statement;
431 {
432 if (s->line_charpos == 0)
433 get_filename_and_charpos (s, line, 0);
434 if (s->fullname == 0)
435 return 0;
436 printf ("\032\032%s:%d:%d:%s\n", s->fullname,
437 line, s->line_charpos[line - 1],
438 mid_statement ? "middle" : "beg");
439 current_source_line = line;
440 first_line_listed = line;
441 last_line_listed = line;
442 current_source_symtab = s;
443 return 1;
444 }
445 \f
446 /* Print source lines from the file of symtab S,
447 starting with line number LINE and stopping before line number STOPLINE. */
448
449 void
450 print_source_lines (s, line, stopline, noerror)
451 struct symtab *s;
452 int line, stopline;
453 int noerror;
454 {
455 register int c;
456 register int desc;
457 register FILE *stream;
458 int nlines = stopline - line;
459
460 desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
461 if (desc < 0)
462 {
463 extern int errno;
464 if (! noerror)
465 perror_with_name (s->filename);
466 print_sys_errmsg (s->filename, errno);
467 return;
468 }
469
470 if (s->line_charpos == 0)
471 find_source_lines (s, desc);
472
473 if (line < 1 || line > s->nlines)
474 {
475 close (desc);
476 error ("Line number out of range; %s has %d lines.",
477 s->filename, s->nlines);
478 }
479
480 if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
481 {
482 close (desc);
483 perror_with_name (s->filename);
484 }
485
486 current_source_symtab = s;
487 current_source_line = line;
488 first_line_listed = line;
489
490 stream = fdopen (desc, "r");
491 clearerr (stream);
492
493 while (nlines-- > 0)
494 {
495 c = fgetc (stream);
496 if (c == EOF) break;
497 last_line_listed = current_source_line;
498 printf ("%d\t", current_source_line++);
499 do
500 {
501 if (c < 040 && c != '\t' && c != '\n')
502 {
503 fputc ('^', stdout);
504 fputc (c + 0100, stdout);
505 }
506 else if (c == 0177)
507 printf ("^?");
508 else
509 fputc (c, stdout);
510 } while (c != '\n' && (c = fgetc (stream)) >= 0);
511 }
512
513 fclose (stream);
514 }
515 \f
516
517
518 /*
519 C++
520 Print a list of files and line numbers which a user may choose from
521 in order to list a function which was specified ambiguously
522 (as with `list classname::overloadedfuncname', for example).
523 The vector in SALS provides the filenames and line numbers.
524 */
525 static void
526 ambiguous_line_spec (sals)
527 struct symtabs_and_lines *sals;
528 {
529 int i;
530
531 for (i = 0; i < sals->nelts; ++i)
532 printf("file: \"%s\", line number: %d\n",
533 sals->sals[i].symtab->filename, sals->sals[i].line);
534 }
535
536
537 static void
538 list_command (arg, from_tty)
539 char *arg;
540 int from_tty;
541 {
542 struct symtabs_and_lines sals, sals_end;
543 struct symtab_and_line sal, sal_end;
544 struct symbol *sym;
545 char *arg1;
546 int no_end = 1;
547 int dummy_end = 0;
548 int dummy_beg = 0;
549 int linenum_beg = 0;
550 char *p;
551
552 if (symtab_list == 0 && partial_symtab_list == 0)
553 error ("Listing source lines requires symbols.");
554
555 /* Pull in a current source symtab if necessary */
556 if (current_source_symtab == 0 &&
557 (arg == 0 || arg[0] == '+' || arg[0] == '-'))
558 select_source_symtab (symtab_list);
559
560 /* "l" or "l +" lists next ten lines. */
561
562 if (arg == 0 || !strcmp (arg, "+"))
563 {
564 if (current_source_symtab == 0)
565 error ("No default source file yet. Do \"help list\".");
566 print_source_lines (current_source_symtab, current_source_line,
567 current_source_line + 10, 0);
568 return;
569 }
570
571 /* "l -" lists previous ten lines, the ones before the ten just listed. */
572 if (!strcmp (arg, "-"))
573 {
574 if (current_source_symtab == 0)
575 error ("No default source file yet. Do \"help list\".");
576 print_source_lines (current_source_symtab,
577 max (first_line_listed - 10, 1),
578 first_line_listed, 0);
579 return;
580 }
581
582 /* Now if there is only one argument, decode it in SAL
583 and set NO_END.
584 If there are two arguments, decode them in SAL and SAL_END
585 and clear NO_END; however, if one of the arguments is blank,
586 set DUMMY_BEG or DUMMY_END to record that fact. */
587
588 arg1 = arg;
589 if (*arg1 == ',')
590 dummy_beg = 1;
591 else
592 {
593 sals = decode_line_1 (&arg1, 0, 0, 0);
594
595 if (! sals.nelts) return; /* C++ */
596 if (sals.nelts > 1)
597 {
598 ambiguous_line_spec (&sals);
599 free (sals.sals);
600 return;
601 }
602
603 sal = sals.sals[0];
604 free (sals.sals);
605 }
606
607 /* Record whether the BEG arg is all digits. */
608
609 for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
610 linenum_beg = (p == arg1);
611
612 while (*arg1 == ' ' || *arg1 == '\t')
613 arg1++;
614 if (*arg1 == ',')
615 {
616 no_end = 0;
617 arg1++;
618 while (*arg1 == ' ' || *arg1 == '\t')
619 arg1++;
620 if (*arg1 == 0)
621 dummy_end = 1;
622 else
623 {
624 if (dummy_beg)
625 sals_end = decode_line_1 (&arg1, 0, 0, 0);
626 else
627 sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
628 if (sals_end.nelts == 0)
629 return;
630 if (sals_end.nelts > 1)
631 {
632 ambiguous_line_spec (&sals_end);
633 free (sals_end.sals);
634 return;
635 }
636 sal_end = sals_end.sals[0];
637 free (sals_end.sals);
638 }
639 }
640
641 if (*arg1)
642 error ("Junk at end of line specification.");
643
644 if (!no_end && !dummy_beg && !dummy_end
645 && sal.symtab != sal_end.symtab)
646 error ("Specified start and end are in different files.");
647 if (dummy_beg && dummy_end)
648 error ("Two empty args do not say what lines to list.");
649
650 /* if line was specified by address,
651 first print exactly which line, and which file.
652 In this case, sal.symtab == 0 means address is outside
653 of all known source files, not that user failed to give a filename. */
654 if (*arg == '*')
655 {
656 if (sal.symtab == 0)
657 error ("No source file for address 0x%x.", sal.pc);
658 sym = find_pc_function (sal.pc);
659 if (sym)
660 printf ("0x%x is in %s (%s, line %d).\n",
661 sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
662 else
663 printf ("0x%x is in %s, line %d.\n",
664 sal.pc, sal.symtab->filename, sal.line);
665 }
666
667 /* If line was not specified by just a line number,
668 and it does not imply a symtab, it must be an undebuggable symbol
669 which means no source code. */
670
671 if (! linenum_beg && sal.symtab == 0)
672 error ("No line number known for %s.", arg);
673
674 /* If this command is repeated with RET,
675 turn it into the no-arg variant. */
676
677 if (from_tty)
678 *arg = 0;
679
680 if (dummy_beg && sal_end.symtab == 0)
681 error ("No default source file yet. Do \"help list\".");
682 if (dummy_beg)
683 print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1),
684 sal_end.line + 1, 0);
685 else if (sal.symtab == 0)
686 error ("No default source file yet. Do \"help list\".");
687 else if (no_end)
688 print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5, 0);
689 else
690 print_source_lines (sal.symtab, sal.line,
691 dummy_end ? sal.line + 10 : sal_end.line + 1,
692 0);
693 }
694 \f
695 /* Print info on range of pc's in a specified line. */
696
697 static void
698 line_info (arg, from_tty)
699 char *arg;
700 int from_tty;
701 {
702 struct symtabs_and_lines sals;
703 struct symtab_and_line sal;
704 int start_pc, end_pc;
705 int i;
706
707 if (arg == 0)
708 {
709 sal.symtab = current_source_symtab;
710 sal.line = last_line_listed;
711 sals.nelts = 1;
712 sals.sals = (struct symtab_and_line *)
713 xmalloc (sizeof (struct symtab_and_line));
714 sals.sals[0] = sal;
715 }
716 else
717 {
718 sals = decode_line_spec_1 (arg, 0);
719
720 /* If this command is repeated with RET,
721 turn it into the no-arg variant. */
722 if (from_tty)
723 *arg = 0;
724 }
725
726 /* C++ More than one line may have been specified, as when the user
727 specifies an overloaded function name. Print info on them all. */
728 for (i = 0; i < sals.nelts; i++)
729 {
730 sal = sals.sals[i];
731
732 if (sal.symtab == 0)
733 error ("No source file specified.");
734
735 if (sal.line > 0
736 && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
737 {
738 if (start_pc == end_pc)
739 printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n",
740 sal.line, sal.symtab->filename, start_pc);
741 else
742 printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n",
743 sal.line, sal.symtab->filename, start_pc, end_pc);
744 /* x/i should display this line's code. */
745 set_next_address (start_pc);
746 /* Repeating "info line" should do the following line. */
747 last_line_listed = sal.line + 1;
748 }
749 else
750 printf ("Line number %d is out of range for \"%s\".\n",
751 sal.line, sal.symtab->filename);
752 }
753 }
754 \f
755 /* Commands to search the source file for a regexp. */
756
757 static void
758 forward_search_command (regex, from_tty)
759 char *regex;
760 {
761 register int c;
762 register int desc;
763 register FILE *stream;
764 int line = last_line_listed + 1;
765 char *msg;
766
767 msg = (char *) re_comp (regex);
768 if (msg)
769 error (msg);
770
771 if (current_source_symtab == 0)
772 error ("No default source file yet. Do \"help list\".");
773
774 /* Search from last_line_listed+1 in current_source_symtab */
775
776 desc = openp (source_path, 0, current_source_symtab->filename,
777 O_RDONLY, 0, &current_source_symtab->fullname);
778 if (desc < 0)
779 perror_with_name (current_source_symtab->filename);
780
781 if (current_source_symtab->line_charpos == 0)
782 find_source_lines (current_source_symtab, desc);
783
784 if (line < 1 || line > current_source_symtab->nlines)
785 {
786 close (desc);
787 error ("Expression not found");
788 }
789
790 if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
791 {
792 close (desc);
793 perror_with_name (current_source_symtab->filename);
794 }
795
796 stream = fdopen (desc, "r");
797 clearerr (stream);
798 while (1) {
799 char buf[4096]; /* Should be reasonable??? */
800 register char *p = buf;
801
802 c = fgetc (stream);
803 if (c == EOF)
804 break;
805 do {
806 *p++ = c;
807 } while (c != '\n' && (c = fgetc (stream)) >= 0);
808
809 /* we now have a source line in buf, null terminate and match */
810 *p = 0;
811 if (re_exec (buf) > 0)
812 {
813 /* Match! */
814 fclose (stream);
815 print_source_lines (current_source_symtab,
816 line, line+1, 0);
817 current_source_line = max (line - 5, 1);
818 return;
819 }
820 line++;
821 }
822
823 printf ("Expression not found\n");
824 fclose (stream);
825 }
826
827 static void
828 reverse_search_command (regex, from_tty)
829 char *regex;
830 {
831 register int c;
832 register int desc;
833 register FILE *stream;
834 int line = last_line_listed - 1;
835 char *msg;
836
837 msg = (char *) re_comp (regex);
838 if (msg)
839 error (msg);
840
841 if (current_source_symtab == 0)
842 error ("No default source file yet. Do \"help list\".");
843
844 /* Search from last_line_listed-1 in current_source_symtab */
845
846 desc = openp (source_path, 0, current_source_symtab->filename,
847 O_RDONLY, 0, &current_source_symtab->fullname);
848 if (desc < 0)
849 perror_with_name (current_source_symtab->filename);
850
851 if (current_source_symtab->line_charpos == 0)
852 find_source_lines (current_source_symtab, desc);
853
854 if (line < 1 || line > current_source_symtab->nlines)
855 {
856 close (desc);
857 error ("Expression not found");
858 }
859
860 if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
861 {
862 close (desc);
863 perror_with_name (current_source_symtab->filename);
864 }
865
866 stream = fdopen (desc, "r");
867 clearerr (stream);
868 while (1)
869 {
870 char buf[4096]; /* Should be reasonable??? */
871 register char *p = buf;
872
873 c = fgetc (stream);
874 if (c == EOF)
875 break;
876 do {
877 *p++ = c;
878 } while (c != '\n' && (c = fgetc (stream)) >= 0);
879
880 /* We now have a source line in buf; null terminate and match. */
881 *p = 0;
882 if (re_exec (buf) > 0)
883 {
884 /* Match! */
885 fclose (stream);
886 print_source_lines (current_source_symtab,
887 line, line+1, 0);
888 current_source_line = max (line - 5, 1);
889 return;
890 }
891 line--;
892 if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
893 {
894 fclose (stream);
895 perror_with_name (current_source_symtab->filename);
896 }
897 }
898
899 printf ("Expression not found\n");
900 fclose (stream);
901 return;
902 }
903 \f
904 void
905 _initialize_source ()
906 {
907 current_source_symtab = 0;
908 init_source_path ();
909
910 add_com ("directory", class_files, directory_command,
911 "Add directory DIR to end of search path for source files.\n\
912 With no argument, reset the search path to just the working directory\n\
913 and forget cached info on line positions in source files.");
914
915 add_info ("directories", directories_info,
916 "Current search path for finding source files.");
917
918 add_info ("line", line_info,
919 "Core addresses of the code for a source line.\n\
920 Line can be specified as\n\
921 LINENUM, to list around that line in current file,\n\
922 FILE:LINENUM, to list around that line in that file,\n\
923 FUNCTION, to list around beginning of that function,\n\
924 FILE:FUNCTION, to distinguish among like-named static functions.\n\
925 Default is to describe the last source line that was listed.\n\n\
926 This sets the default address for \"x\" to the line's first instruction\n\
927 so that \"x/i\" suffices to start examining the machine code.\n\
928 The address is also stored as the value of \"$_\".");
929
930 add_com ("forward-search", class_files, forward_search_command,
931 "Search for regular expression (see regex(3)) from last line listed.");
932 add_com_alias ("search", "forward-search", class_files, 0);
933
934 add_com ("reverse-search", class_files, reverse_search_command,
935 "Search backward for regular expression (see regex(3)) from last line listed.");
936
937 add_com ("list", class_files, list_command,
938 "List specified function or line.\n\
939 With no argument, lists ten more lines after or around previous listing.\n\
940 \"list -\" lists the ten lines before a previous ten-line listing.\n\
941 One argument specifies a line, and ten lines are listed around that line.\n\
942 Two arguments with comma between specify starting and ending lines to list.\n\
943 Lines can be specified in these ways:\n\
944 LINENUM, to list around that line in current file,\n\
945 FILE:LINENUM, to list around that line in that file,\n\
946 FUNCTION, to list around beginning of that function,\n\
947 FILE:FUNCTION, to distinguish among like-named static functions.\n\
948 *ADDRESS, to list around the line containing that address.\n\
949 With two args if one is empty it stands for ten lines away from the other arg.");
950 }
951