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