OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [source.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* List lines of source files for GDB, the GNU debugger.
2
   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
3
   1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 59 Temple Place - Suite 330,
20
   Boston, MA 02111-1307, USA.  */
21
 
22
#include "defs.h"
23
#include "symtab.h"
24
#include "expression.h"
25
#include "language.h"
26
#include "command.h"
27
#include "source.h"
28
#include "gdbcmd.h"
29
#include "frame.h"
30
#include "value.h"
31
 
32
#include <sys/types.h>
33
#include "gdb_string.h"
34
#include "gdb_stat.h"
35
#include <fcntl.h>
36
#include "gdbcore.h"
37
#include "gdb_regex.h"
38
#include "symfile.h"
39
#include "objfiles.h"
40
#include "annotate.h"
41
#include "gdbtypes.h"
42
#include "linespec.h"
43
#include "filenames.h"          /* for DOSish file names */
44
#ifdef UI_OUT
45
#include "ui-out.h"
46
#endif
47
 
48
#ifdef CRLF_SOURCE_FILES
49
 
50
/* Define CRLF_SOURCE_FILES in an xm-*.h file if source files on the
51
   host use \r\n rather than just \n.  Defining CRLF_SOURCE_FILES is
52
   much faster than defining LSEEK_NOT_LINEAR.  */
53
 
54
#ifndef O_BINARY
55
#define O_BINARY 0
56
#endif
57
 
58
#define OPEN_MODE (O_RDONLY | O_BINARY)
59
#define FDOPEN_MODE FOPEN_RB
60
 
61
#else /* ! defined (CRLF_SOURCE_FILES) */
62
 
63
#define OPEN_MODE O_RDONLY
64
#define FDOPEN_MODE FOPEN_RT
65
 
66
#endif /* ! defined (CRLF_SOURCE_FILES) */
67
 
68
/* Prototypes for exported functions. */
69
 
70
void _initialize_source (void);
71
 
72
/* Prototypes for local functions. */
73
 
74
static int get_filename_and_charpos (struct symtab *, char **);
75
 
76
static void reverse_search_command (char *, int);
77
 
78
static void forward_search_command (char *, int);
79
 
80
static void line_info (char *, int);
81
 
82
static void list_command (char *, int);
83
 
84
static void ambiguous_line_spec (struct symtabs_and_lines *);
85
 
86
static void source_info (char *, int);
87
 
88
static void show_directories (char *, int);
89
 
90
/* Path of directories to search for source files.
91
   Same format as the PATH environment variable's value.  */
92
 
93
char *source_path;
94
 
95
/* Symtab of default file for listing lines of.  */
96
 
97
struct symtab *current_source_symtab;
98
 
99
/* Default next line to list.  */
100
 
101
int current_source_line;
102
 
103
/* Default number of lines to print with commands like "list".
104
   This is based on guessing how many long (i.e. more than chars_per_line
105
   characters) lines there will be.  To be completely correct, "list"
106
   and friends should be rewritten to count characters and see where
107
   things are wrapping, but that would be a fair amount of work.  */
108
 
109
int lines_to_list = 10;
110
 
111
/* Line number of last line printed.  Default for various commands.
112
   current_source_line is usually, but not always, the same as this.  */
113
 
114
static int last_line_listed;
115
 
116
/* First line number listed by last listing command.  */
117
 
118
static int first_line_listed;
119
 
120
/* Saves the name of the last source file visited and a possible error code.
121
   Used to prevent repeating annoying "No such file or directories" msgs */
122
 
123
static struct symtab *last_source_visited = NULL;
124
static int last_source_error = 0;
125
 
126
 
127
/* Set the source file default for the "list" command to be S.
128
 
129
   If S is NULL, and we don't have a default, find one.  This
130
   should only be called when the user actually tries to use the
131
   default, since we produce an error if we can't find a reasonable
132
   default.  Also, since this can cause symbols to be read, doing it
133
   before we need to would make things slower than necessary.  */
134
 
135
void
136
select_source_symtab (register struct symtab *s)
137
{
138
  struct symtabs_and_lines sals;
139
  struct symtab_and_line sal;
140
  struct partial_symtab *ps;
141
  struct partial_symtab *cs_pst = 0;
142
  struct objfile *ofp;
143
 
144
  if (s)
145
    {
146
      current_source_symtab = s;
147
      current_source_line = 1;
148
      return;
149
    }
150
 
151
  if (current_source_symtab)
152
    return;
153
 
154
  /* Make the default place to list be the function `main'
155
     if one exists.  */
156
  if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0, NULL))
157
    {
158
      sals = decode_line_spec ("main", 1);
159
      sal = sals.sals[0];
160
      xfree (sals.sals);
161
      current_source_symtab = sal.symtab;
162
      current_source_line = max (sal.line - (lines_to_list - 1), 1);
163
      if (current_source_symtab)
164
        return;
165
    }
166
 
167
  /* All right; find the last file in the symtab list (ignoring .h's).  */
168
 
169
  current_source_line = 1;
170
 
171
  for (ofp = object_files; ofp != NULL; ofp = ofp->next)
172
    {
173
      for (s = ofp->symtabs; s; s = s->next)
174
        {
175
          char *name = s->filename;
176
          int len = strlen (name);
177
          if (!(len > 2 && (STREQ (&name[len - 2], ".h"))))
178
            {
179
              current_source_symtab = s;
180
            }
181
        }
182
    }
183
  if (current_source_symtab)
184
    return;
185
 
186
  /* Howabout the partial symbol tables? */
187
 
188
  for (ofp = object_files; ofp != NULL; ofp = ofp->next)
189
    {
190
      for (ps = ofp->psymtabs; ps != NULL; ps = ps->next)
191
        {
192
          char *name = ps->filename;
193
          int len = strlen (name);
194
          if (!(len > 2 && (STREQ (&name[len - 2], ".h"))))
195
            {
196
              cs_pst = ps;
197
            }
198
        }
199
    }
200
  if (cs_pst)
201
    {
202
      if (cs_pst->readin)
203
        {
204
          internal_error (__FILE__, __LINE__,
205
                          "select_source_symtab: "
206
                          "readin pst found and no symtabs.");
207
        }
208
      else
209
        {
210
          current_source_symtab = PSYMTAB_TO_SYMTAB (cs_pst);
211
        }
212
    }
213
  if (current_source_symtab)
214
    return;
215
 
216
  error ("Can't find a default source file");
217
}
218
 
219
static void
220
show_directories (char *ignore, int from_tty)
221
{
222
  puts_filtered ("Source directories searched: ");
223
  puts_filtered (source_path);
224
  puts_filtered ("\n");
225
}
226
 
227
/* Forget what we learned about line positions in source files, and
228
   which directories contain them; must check again now since files
229
   may be found in a different directory now.  */
230
 
231
void
232
forget_cached_source_info (void)
233
{
234
  register struct symtab *s;
235
  register struct objfile *objfile;
236
 
237
  for (objfile = object_files; objfile != NULL; objfile = objfile->next)
238
    {
239
      for (s = objfile->symtabs; s != NULL; s = s->next)
240
        {
241
          if (s->line_charpos != NULL)
242
            {
243
              mfree (objfile->md, s->line_charpos);
244
              s->line_charpos = NULL;
245
            }
246
          if (s->fullname != NULL)
247
            {
248
              mfree (objfile->md, s->fullname);
249
              s->fullname = NULL;
250
            }
251
        }
252
    }
253
}
254
 
255
void
256
init_source_path (void)
257
{
258
  char buf[20];
259
 
260
  sprintf (buf, "$cdir%c$cwd", DIRNAME_SEPARATOR);
261
  source_path = xstrdup (buf);
262
  forget_cached_source_info ();
263
}
264
 
265
/* Add zero or more directories to the front of the source path.  */
266
 
267
void
268
directory_command (char *dirname, int from_tty)
269
{
270
  dont_repeat ();
271
  /* FIXME, this goes to "delete dir"... */
272
  if (dirname == 0)
273
    {
274
      if (from_tty && query ("Reinitialize source path to empty? "))
275
        {
276
          xfree (source_path);
277
          init_source_path ();
278
        }
279
    }
280
  else
281
    {
282
      mod_path (dirname, &source_path);
283
      last_source_visited = NULL;
284
    }
285
  if (from_tty)
286
    show_directories ((char *) 0, from_tty);
287
  forget_cached_source_info ();
288
}
289
 
290
/* Add zero or more directories to the front of an arbitrary path.  */
291
 
292
void
293
mod_path (char *dirname, char **which_path)
294
{
295
  char *old = *which_path;
296
  int prefix = 0;
297
 
298
  if (dirname == 0)
299
    return;
300
 
301
  dirname = xstrdup (dirname);
302
  make_cleanup (xfree, dirname);
303
 
304
  do
305
    {
306
      char *name = dirname;
307
      register char *p;
308
      struct stat st;
309
 
310
      {
311
        char *separator = strchr (name, DIRNAME_SEPARATOR);
312
        char *space = strchr (name, ' ');
313
        char *tab = strchr (name, '\t');
314
 
315
        if (separator == 0 && space == 0 && tab == 0)
316
          p = dirname = name + strlen (name);
317
        else
318
          {
319
            p = 0;
320
            if (separator != 0 && (p == 0 || separator < p))
321
              p = separator;
322
            if (space != 0 && (p == 0 || space < p))
323
              p = space;
324
            if (tab != 0 && (p == 0 || tab < p))
325
              p = tab;
326
            dirname = p + 1;
327
            while (*dirname == DIRNAME_SEPARATOR
328
                   || *dirname == ' '
329
                   || *dirname == '\t')
330
              ++dirname;
331
          }
332
      }
333
 
334
      if (!(IS_DIR_SEPARATOR (*name) && p <= name + 1)   /* "/" */
335
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
336
      /* On MS-DOS and MS-Windows, h:\ is different from h: */
337
          && !(p == name + 3 && name[1] == ':')          /* "d:/" */
338
#endif
339
          && IS_DIR_SEPARATOR (p[-1]))
340
        /* Sigh. "foo/" => "foo" */
341
        --p;
342
      *p = '\0';
343
 
344
      while (p > name && p[-1] == '.')
345
        {
346
          if (p - name == 1)
347
            {
348
              /* "." => getwd ().  */
349
              name = current_directory;
350
              goto append;
351
            }
352
          else if (p > name + 1 && IS_DIR_SEPARATOR (p[-2]))
353
            {
354
              if (p - name == 2)
355
                {
356
                  /* "/." => "/".  */
357
                  *--p = '\0';
358
                  goto append;
359
                }
360
              else
361
                {
362
                  /* "...foo/." => "...foo".  */
363
                  p -= 2;
364
                  *p = '\0';
365
                  continue;
366
                }
367
            }
368
          else
369
            break;
370
        }
371
 
372
      if (name[0] == '~')
373
        name = tilde_expand (name);
374
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
375
      else if (IS_ABSOLUTE_PATH (name) && p == name + 2) /* "d:" => "d:." */
376
        name = concat (name, ".", NULL);
377
#endif
378
      else if (!IS_ABSOLUTE_PATH (name) && name[0] != '$')
379
        name = concat (current_directory, SLASH_STRING, name, NULL);
380
      else
381
        name = savestring (name, p - name);
382
      make_cleanup (xfree, name);
383
 
384
      /* Unless it's a variable, check existence.  */
385
      if (name[0] != '$')
386
        {
387
          /* These are warnings, not errors, since we don't want a
388
             non-existent directory in a .gdbinit file to stop processing
389
             of the .gdbinit file.
390
 
391
             Whether they get added to the path is more debatable.  Current
392
             answer is yes, in case the user wants to go make the directory
393
             or whatever.  If the directory continues to not exist/not be
394
             a directory/etc, then having them in the path should be
395
             harmless.  */
396
          if (stat (name, &st) < 0)
397
            {
398
              int save_errno = errno;
399
              fprintf_unfiltered (gdb_stderr, "Warning: ");
400
              print_sys_errmsg (name, save_errno);
401
            }
402
          else if ((st.st_mode & S_IFMT) != S_IFDIR)
403
            warning ("%s is not a directory.", name);
404
        }
405
 
406
    append:
407
      {
408
        register unsigned int len = strlen (name);
409
 
410
        p = *which_path;
411
        while (1)
412
          {
413
            /* FIXME: strncmp loses in interesting ways on MS-DOS and
414
               MS-Windows because of case-insensitivity and two different
415
               but functionally identical slash characters.  We need a
416
               special filesystem-dependent file-name comparison function.
417
 
418
               Actually, even on Unix I would use realpath() or its work-
419
               alike before comparing.  Then all the code above which
420
               removes excess slashes and dots could simply go away.  */
421
            if (!strncmp (p, name, len)
422
                && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR))
423
              {
424
                /* Found it in the search path, remove old copy */
425
                if (p > *which_path)
426
                  p--;          /* Back over leading separator */
427
                if (prefix > p - *which_path)
428
                  goto skip_dup;        /* Same dir twice in one cmd */
429
                strcpy (p, &p[len + 1]);        /* Copy from next \0 or  : */
430
              }
431
            p = strchr (p, DIRNAME_SEPARATOR);
432
            if (p != 0)
433
              ++p;
434
            else
435
              break;
436
          }
437
        if (p == 0)
438
          {
439
            char tinybuf[2];
440
 
441
            tinybuf[0] = DIRNAME_SEPARATOR;
442
            tinybuf[1] = '\0';
443
 
444
            /* 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.  */
445
            if (prefix)
446
              {
447
                char *temp, c;
448
 
449
                c = old[prefix];
450
                old[prefix] = '\0';
451
                temp = concat (old, tinybuf, name, NULL);
452
                old[prefix] = c;
453
                *which_path = concat (temp, "", &old[prefix], NULL);
454
                prefix = strlen (temp);
455
                xfree (temp);
456
              }
457
            else
458
              {
459
                *which_path = concat (name, (old[0] ? tinybuf : old), old, NULL);
460
                prefix = strlen (name);
461
              }
462
            xfree (old);
463
            old = *which_path;
464
          }
465
      }
466
    skip_dup:;
467
    }
468
  while (*dirname != '\0');
469
}
470
 
471
 
472
static void
473
source_info (char *ignore, int from_tty)
474
{
475
  register struct symtab *s = current_source_symtab;
476
 
477
  if (!s)
478
    {
479
      printf_filtered ("No current source file.\n");
480
      return;
481
    }
482
  printf_filtered ("Current source file is %s\n", s->filename);
483
  if (s->dirname)
484
    printf_filtered ("Compilation directory is %s\n", s->dirname);
485
  if (s->fullname)
486
    printf_filtered ("Located in %s\n", s->fullname);
487
  if (s->nlines)
488
    printf_filtered ("Contains %d line%s.\n", s->nlines,
489
                     s->nlines == 1 ? "" : "s");
490
 
491
  printf_filtered ("Source language is %s.\n", language_str (s->language));
492
  printf_filtered ("Compiled with %s debugging format.\n", s->debugformat);
493
}
494
 
495
 
496
 
497
/* Open a file named STRING, searching path PATH (dir names sep by some char)
498
   using mode MODE and protection bits PROT in the calls to open.
499
 
500
   If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
501
   (ie pretend the first element of PATH is ".").  This also indicates
502
   that a slash in STRING disables searching of the path (this is
503
   so that "exec-file ./foo" or "symbol-file ./foo" insures that you
504
   get that particular version of foo or an error message).
505
 
506
   If FILENAME_OPENED is non-null, set it to a newly allocated string naming
507
   the actual file opened (this string will always start with a "/".  We
508
   have to take special pains to avoid doubling the "/" between the directory
509
   and the file, sigh!  Emacs gets confuzzed by this when we print the
510
   source file name!!!
511
 
512
   If a file is found, return the descriptor.
513
   Otherwise, return -1, with errno set for the last name we tried to open.  */
514
 
515
/*  >>>> This should only allow files of certain types,
516
   >>>>  eg executable, non-directory */
517
int
518
openp (const char *path, int try_cwd_first, const char *string,
519
       int mode, int prot,
520
       char **filename_opened)
521
{
522
  register int fd;
523
  register char *filename;
524
  const char *p;
525
  const char *p1;
526
  register int len;
527
  int alloclen;
528
 
529
  if (!path)
530
    path = ".";
531
 
532
#if defined(_WIN32) || defined(__CYGWIN__)
533
  mode |= O_BINARY;
534
#endif
535
 
536
  if (try_cwd_first || IS_ABSOLUTE_PATH (string))
537
    {
538
      int i;
539
      filename = alloca (strlen (string) + 1);
540
      strcpy (filename, string);
541
      fd = open (filename, mode, prot);
542
      if (fd >= 0)
543
        goto done;
544
      for (i = 0; string[i]; i++)
545
        if (IS_DIR_SEPARATOR (string[i]))
546
          goto done;
547
    }
548
 
549
  /* ./foo => foo */
550
  while (string[0] == '.' && IS_DIR_SEPARATOR (string[1]))
551
    string += 2;
552
 
553
  alloclen = strlen (path) + strlen (string) + 2;
554
  filename = alloca (alloclen);
555
  fd = -1;
556
  for (p = path; p; p = p1 ? p1 + 1 : 0)
557
    {
558
      p1 = strchr (p, DIRNAME_SEPARATOR);
559
      if (p1)
560
        len = p1 - p;
561
      else
562
        len = strlen (p);
563
 
564
      if (len == 4 && p[0] == '$' && p[1] == 'c'
565
          && p[2] == 'w' && p[3] == 'd')
566
        {
567
          /* Name is $cwd -- insert current directory name instead.  */
568
          int newlen;
569
 
570
          /* First, realloc the filename buffer if too short. */
571
          len = strlen (current_directory);
572
          newlen = len + strlen (string) + 2;
573
          if (newlen > alloclen)
574
            {
575
              alloclen = newlen;
576
              filename = alloca (alloclen);
577
            }
578
          strcpy (filename, current_directory);
579
        }
580
      else
581
        {
582
          /* Normal file name in path -- just use it.  */
583
          strncpy (filename, p, len);
584
          filename[len] = 0;
585
        }
586
 
587
      /* Remove trailing slashes */
588
      while (len > 0 && IS_DIR_SEPARATOR (filename[len - 1]))
589
        filename[--len] = 0;
590
 
591
      strcat (filename + len, SLASH_STRING);
592
      strcat (filename, string);
593
 
594
      fd = open (filename, mode);
595
      if (fd >= 0)
596
        break;
597
    }
598
 
599
done:
600
  if (filename_opened)
601
    {
602
      if (fd < 0)
603
        *filename_opened = NULL;
604
      else if (IS_ABSOLUTE_PATH (filename))
605
        *filename_opened = savestring (filename, strlen (filename));
606
      else
607
        {
608
          /* Beware the // my son, the Emacs barfs, the botch that catch... */
609
 
610
          *filename_opened = concat (current_directory,
611
           IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
612
                                     ? "" : SLASH_STRING,
613
                                     filename, NULL);
614
        }
615
    }
616
  /* OBSOLETE #ifdef MPW  */
617
  /* OBSOLETE This is a debugging hack that can go away when all combinations */
618
  /* OBSOLETE of Mac and Unix names are handled reasonably.  */
619
  /* OBSOLETE   { */
620
  /* OBSOLETE     extern int debug_openp; */
621
  /* OBSOLETE  */
622
  /* OBSOLETE     if (debug_openp) */
623
  /* OBSOLETE       { */
624
  /* OBSOLETE   printf ("openp on %s, path %s mode %d prot %d\n  returned %d", */
625
  /* OBSOLETE           string, path, mode, prot, fd); */
626
  /* OBSOLETE   if (*filename_opened) */
627
  /* OBSOLETE     printf (" (filename is %s)", *filename_opened); */
628
  /* OBSOLETE   printf ("\n"); */
629
  /* OBSOLETE       } */
630
  /* OBSOLETE   } */
631
  /* OBSOLETE #endif  *//* MPW */
632
 
633
  return fd;
634
}
635
 
636
 
637
/* This is essentially a convenience, for clients that want the behaviour
638
   of openp, using source_path, but that really don't want the file to be
639
   opened but want instead just to know what the full pathname is (as
640
   qualified against source_path).
641
 
642
   The current working directory is searched first.
643
 
644
   If the file was found, this function returns 1, and FULL_PATHNAME is
645
   set to the fully-qualified pathname.
646
 
647
   Else, this functions returns 0, and FULL_PATHNAME is set to NULL.
648
 */
649
int
650
source_full_path_of (char *filename, char **full_pathname)
651
{
652
  int fd;
653
 
654
  fd = openp (source_path, 1, filename, O_RDONLY, 0, full_pathname);
655
  if (fd < 0)
656
    {
657
      *full_pathname = NULL;
658
      return 0;
659
    }
660
 
661
  close (fd);
662
  return 1;
663
}
664
 
665
 
666
/* Open a source file given a symtab S.  Returns a file descriptor or
667
   negative number for error.  */
668
 
669
int
670
open_source_file (struct symtab *s)
671
{
672
  char *path = source_path;
673
  const char *p;
674
  int result;
675
  char *fullname;
676
 
677
  /* Quick way out if we already know its full name */
678
  if (s->fullname)
679
    {
680
      result = open (s->fullname, OPEN_MODE);
681
      if (result >= 0)
682
        return result;
683
      /* Didn't work -- free old one, try again. */
684
      mfree (s->objfile->md, s->fullname);
685
      s->fullname = NULL;
686
    }
687
 
688
  if (s->dirname != NULL)
689
    {
690
      /* Replace a path entry of  $cdir  with the compilation directory name */
691
#define cdir_len        5
692
      /* We cast strstr's result in case an ANSIhole has made it const,
693
         which produces a "required warning" when assigned to a nonconst. */
694
      p = (char *) strstr (source_path, "$cdir");
695
      if (p && (p == path || p[-1] == DIRNAME_SEPARATOR)
696
          && (p[cdir_len] == DIRNAME_SEPARATOR || p[cdir_len] == '\0'))
697
        {
698
          int len;
699
 
700
          path = (char *)
701
            alloca (strlen (source_path) + 1 + strlen (s->dirname) + 1);
702
          len = p - source_path;
703
          strncpy (path, source_path, len);     /* Before $cdir */
704
          strcpy (path + len, s->dirname);      /* new stuff */
705
          strcat (path + len, source_path + len + cdir_len);    /* After $cdir */
706
        }
707
    }
708
 
709
  result = openp (path, 0, s->filename, OPEN_MODE, 0, &s->fullname);
710
  if (result < 0)
711
    {
712
      /* Didn't work.  Try using just the basename. */
713
      p = lbasename (s->filename);
714
      if (p != s->filename)
715
        result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname);
716
    }
717
  /* OBSOLETE #ifdef MPW */
718
  /* OBSOLETE   if (result < 0) */
719
  /* OBSOLETE     { */
720
  /* OBSOLETE        *//* Didn't work.  Try using just the MPW basename. */
721
  /* OBSOLETE       p = (char *) mpw_basename (s->filename); */
722
  /* OBSOLETE       if (p != s->filename) */
723
  /* OBSOLETE   result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname); */
724
  /* OBSOLETE     } */
725
  /* OBSOLETE   if (result < 0) */
726
  /* OBSOLETE     { */
727
  /* OBSOLETE        *//* Didn't work.  Try using the mixed Unix/MPW basename. */
728
  /* OBSOLETE       p = (char *) mpw_mixed_basename (s->filename); */
729
  /* OBSOLETE       if (p != s->filename) */
730
  /* OBSOLETE   result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname); */
731
  /* OBSOLETE     } */
732
  /* OBSOLETE #endif MPW */
733
 
734
  if (result >= 0)
735
    {
736
      fullname = s->fullname;
737
      s->fullname = mstrsave (s->objfile->md, s->fullname);
738
      xfree (fullname);
739
    }
740
  return result;
741
}
742
 
743
/* Return the path to the source file associated with symtab.  Returns NULL
744
   if no symtab.  */
745
 
746
char *
747
symtab_to_filename (struct symtab *s)
748
{
749
  int fd;
750
 
751
  if (!s)
752
    return NULL;
753
 
754
  /* If we've seen the file before, just return fullname. */
755
 
756
  if (s->fullname)
757
    return s->fullname;
758
 
759
  /* Try opening the file to setup fullname */
760
 
761
  fd = open_source_file (s);
762
  if (fd < 0)
763
    return s->filename;         /* File not found.  Just use short name */
764
 
765
  /* Found the file.  Cleanup and return the full name */
766
 
767
  close (fd);
768
  return s->fullname;
769
}
770
 
771
 
772
/* Create and initialize the table S->line_charpos that records
773
   the positions of the lines in the source file, which is assumed
774
   to be open on descriptor DESC.
775
   All set S->nlines to the number of such lines.  */
776
 
777
void
778
find_source_lines (struct symtab *s, int desc)
779
{
780
  struct stat st;
781
  register char *data, *p, *end;
782
  int nlines = 0;
783
  int lines_allocated = 1000;
784
  int *line_charpos;
785
  long mtime = 0;
786
  int size;
787
 
788
  line_charpos = (int *) xmmalloc (s->objfile->md,
789
                                   lines_allocated * sizeof (int));
790
  if (fstat (desc, &st) < 0)
791
    perror_with_name (s->filename);
792
 
793
  if (s && s->objfile && s->objfile->obfd)
794
    mtime = bfd_get_mtime (s->objfile->obfd);
795
  else if (exec_bfd)
796
    mtime = bfd_get_mtime (exec_bfd);
797
 
798
  if (mtime && mtime < st.st_mtime)
799
    {
800
      if (tui_version)
801
        printf_filtered ("\n");
802
      warning ("Source file is more recent than executable.\n");
803
    }
804
 
805
#ifdef LSEEK_NOT_LINEAR
806
  {
807
    char c;
808
 
809
    /* Have to read it byte by byte to find out where the chars live */
810
 
811
    line_charpos[0] = lseek (desc, 0, SEEK_CUR);
812
    nlines = 1;
813
    while (myread (desc, &c, 1) > 0)
814
      {
815
        if (c == '\n')
816
          {
817
            if (nlines == lines_allocated)
818
              {
819
                lines_allocated *= 2;
820
                line_charpos =
821
                  (int *) xmrealloc (s->objfile->md, (char *) line_charpos,
822
                                     sizeof (int) * lines_allocated);
823
              }
824
            line_charpos[nlines++] = lseek (desc, 0, SEEK_CUR);
825
          }
826
      }
827
  }
828
#else /* lseek linear.  */
829
  {
830
    struct cleanup *old_cleanups;
831
 
832
    /* st_size might be a large type, but we only support source files whose
833
       size fits in an int.  */
834
    size = (int) st.st_size;
835
 
836
    /* Use malloc, not alloca, because this may be pretty large, and we may
837
       run into various kinds of limits on stack size.  */
838
    data = (char *) xmalloc (size);
839
    old_cleanups = make_cleanup (xfree, data);
840
 
841
    /* Reassign `size' to result of read for systems where \r\n -> \n.  */
842
    size = myread (desc, data, size);
843
    if (size < 0)
844
      perror_with_name (s->filename);
845
    end = data + size;
846
    p = data;
847
    line_charpos[0] = 0;
848
    nlines = 1;
849
    while (p != end)
850
      {
851
        if (*p++ == '\n'
852
        /* A newline at the end does not start a new line.  */
853
            && p != end)
854
          {
855
            if (nlines == lines_allocated)
856
              {
857
                lines_allocated *= 2;
858
                line_charpos =
859
                  (int *) xmrealloc (s->objfile->md, (char *) line_charpos,
860
                                     sizeof (int) * lines_allocated);
861
              }
862
            line_charpos[nlines++] = p - data;
863
          }
864
      }
865
    do_cleanups (old_cleanups);
866
  }
867
#endif /* lseek linear.  */
868
  s->nlines = nlines;
869
  s->line_charpos =
870
    (int *) xmrealloc (s->objfile->md, (char *) line_charpos,
871
                       nlines * sizeof (int));
872
 
873
}
874
 
875
/* Return the character position of a line LINE in symtab S.
876
   Return 0 if anything is invalid.  */
877
 
878
#if 0                           /* Currently unused */
879
 
880
int
881
source_line_charpos (struct symtab *s, int line)
882
{
883
  if (!s)
884
    return 0;
885
  if (!s->line_charpos || line <= 0)
886
    return 0;
887
  if (line > s->nlines)
888
    line = s->nlines;
889
  return s->line_charpos[line - 1];
890
}
891
 
892
/* Return the line number of character position POS in symtab S.  */
893
 
894
int
895
source_charpos_line (register struct symtab *s, register int chr)
896
{
897
  register int line = 0;
898
  register int *lnp;
899
 
900
  if (s == 0 || s->line_charpos == 0)
901
    return 0;
902
  lnp = s->line_charpos;
903
  /* Files are usually short, so sequential search is Ok */
904
  while (line < s->nlines && *lnp <= chr)
905
    {
906
      line++;
907
      lnp++;
908
    }
909
  if (line >= s->nlines)
910
    line = s->nlines;
911
  return line;
912
}
913
 
914
#endif /* 0 */
915
 
916
 
917
/* Get full pathname and line number positions for a symtab.
918
   Return nonzero if line numbers may have changed.
919
   Set *FULLNAME to actual name of the file as found by `openp',
920
   or to 0 if the file is not found.  */
921
 
922
static int
923
get_filename_and_charpos (struct symtab *s, char **fullname)
924
{
925
  register int desc, linenums_changed = 0;
926
 
927
  desc = open_source_file (s);
928
  if (desc < 0)
929
    {
930
      if (fullname)
931
        *fullname = NULL;
932
      return 0;
933
    }
934
  if (fullname)
935
    *fullname = s->fullname;
936
  if (s->line_charpos == 0)
937
    linenums_changed = 1;
938
  if (linenums_changed)
939
    find_source_lines (s, desc);
940
  close (desc);
941
  return linenums_changed;
942
}
943
 
944
/* Print text describing the full name of the source file S
945
   and the line number LINE and its corresponding character position.
946
   The text starts with two Ctrl-z so that the Emacs-GDB interface
947
   can easily find it.
948
 
949
   MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
950
 
951
   Return 1 if successful, 0 if could not find the file.  */
952
 
953
int
954
identify_source_line (struct symtab *s, int line, int mid_statement,
955
                      CORE_ADDR pc)
956
{
957
  if (s->line_charpos == 0)
958
    get_filename_and_charpos (s, (char **) NULL);
959
  if (s->fullname == 0)
960
    return 0;
961
  if (line > s->nlines)
962
    /* Don't index off the end of the line_charpos array.  */
963
    return 0;
964
  annotate_source (s->fullname, line, s->line_charpos[line - 1],
965
                   mid_statement, pc);
966
 
967
  current_source_line = line;
968
  first_line_listed = line;
969
  last_line_listed = line;
970
  current_source_symtab = s;
971
  return 1;
972
}
973
 
974
 
975
/* Print source lines from the file of symtab S,
976
   starting with line number LINE and stopping before line number STOPLINE. */
977
 
978
static void print_source_lines_base (struct symtab *s, int line, int stopline,
979
                                     int noerror);
980
static void
981
print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
982
{
983
  register int c;
984
  register int desc;
985
  register FILE *stream;
986
  int nlines = stopline - line;
987
 
988
  /* Regardless of whether we can open the file, set current_source_symtab. */
989
  current_source_symtab = s;
990
  current_source_line = line;
991
  first_line_listed = line;
992
 
993
#ifdef UI_OUT
994
  /* If printing of source lines is disabled, just print file and line number */
995
  if (ui_out_test_flags (uiout, ui_source_list))
996
    {
997
#endif
998
      /* Only prints "No such file or directory" once */
999
      if ((s != last_source_visited) || (!last_source_error))
1000
        {
1001
          last_source_visited = s;
1002
          desc = open_source_file (s);
1003
        }
1004
      else
1005
        {
1006
          desc = last_source_error;
1007
          noerror = 1;
1008
        }
1009
#ifdef UI_OUT
1010
    }
1011
  else
1012
    {
1013
      desc = -1;
1014
      noerror = 1;
1015
    }
1016
#endif
1017
 
1018
  if (desc < 0)
1019
    {
1020
      last_source_error = desc;
1021
 
1022
      if (!noerror)
1023
        {
1024
          char *name = alloca (strlen (s->filename) + 100);
1025
          sprintf (name, "%d\t%s", line, s->filename);
1026
          print_sys_errmsg (name, errno);
1027
        }
1028
      else
1029
#ifdef UI_OUT
1030
        ui_out_field_int (uiout, "line", line);
1031
      ui_out_text (uiout, "\tin ");
1032
      ui_out_field_string (uiout, "file", s->filename);
1033
      ui_out_text (uiout, "\n");
1034
#else
1035
        printf_filtered ("%d\tin %s\n", line, s->filename);
1036
#endif
1037
 
1038
      return;
1039
    }
1040
 
1041
  last_source_error = 0;
1042
 
1043
  if (s->line_charpos == 0)
1044
    find_source_lines (s, desc);
1045
 
1046
  if (line < 1 || line > s->nlines)
1047
    {
1048
      close (desc);
1049
      error ("Line number %d out of range; %s has %d lines.",
1050
             line, s->filename, s->nlines);
1051
    }
1052
 
1053
  if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
1054
    {
1055
      close (desc);
1056
      perror_with_name (s->filename);
1057
    }
1058
 
1059
  stream = fdopen (desc, FDOPEN_MODE);
1060
  clearerr (stream);
1061
 
1062
  while (nlines-- > 0)
1063
    {
1064
#ifdef UI_OUT
1065
      char buf[20];
1066
 
1067
      c = fgetc (stream);
1068
      if (c == EOF)
1069
        break;
1070
      last_line_listed = current_source_line;
1071
      sprintf (buf, "%d\t", current_source_line++);
1072
      ui_out_text (uiout, buf);
1073
      do
1074
        {
1075
          if (c < 040 && c != '\t' && c != '\n' && c != '\r')
1076
            {
1077
              sprintf (buf, "^%c", c + 0100);
1078
              ui_out_text (uiout, buf);
1079
            }
1080
          else if (c == 0177)
1081
            ui_out_text (uiout, "^?");
1082
#ifdef CRLF_SOURCE_FILES
1083
          else if (c == '\r')
1084
            {
1085
              /* Skip a \r character, but only before a \n.  */
1086
              int c1 = fgetc (stream);
1087
 
1088
              if (c1 != '\n')
1089
                printf_filtered ("^%c", c + 0100);
1090
              if (c1 != EOF)
1091
                ungetc (c1, stream);
1092
            }
1093
#endif
1094
          else
1095
            {
1096
              sprintf (buf, "%c", c);
1097
              ui_out_text (uiout, buf);
1098
            }
1099
        }
1100
      while (c != '\n' && (c = fgetc (stream)) >= 0);
1101
#else
1102
      c = fgetc (stream);
1103
      if (c == EOF)
1104
        break;
1105
      last_line_listed = current_source_line;
1106
      printf_filtered ("%d\t", current_source_line++);
1107
      do
1108
        {
1109
          if (c < 040 && c != '\t' && c != '\n' && c != '\r')
1110
            printf_filtered ("^%c", c + 0100);
1111
          else if (c == 0177)
1112
            printf_filtered ("^?");
1113
#ifdef CRLF_SOURCE_FILES
1114
          else if (c == '\r')
1115
            {
1116
              /* Just skip \r characters.  */
1117
            }
1118
#endif
1119
          else
1120
            printf_filtered ("%c", c);
1121
        }
1122
      while (c != '\n' && (c = fgetc (stream)) >= 0);
1123
#endif
1124
    }
1125
 
1126
  fclose (stream);
1127
}
1128
 
1129
/* Show source lines from the file of symtab S, starting with line
1130
   number LINE and stopping before line number STOPLINE.  If this is the
1131
   not the command line version, then the source is shown in the source
1132
   window otherwise it is simply printed */
1133
 
1134
void
1135
print_source_lines (struct symtab *s, int line, int stopline, int noerror)
1136
{
1137
#if defined(TUI)
1138
  if (!tui_version ||
1139
      m_winPtrIsNull (srcWin) || !srcWin->generic.isVisible)
1140
    print_source_lines_base (s, line, stopline, noerror);
1141
  else
1142
    {
1143
      TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
1144
extern void tui_vAddWinToLayout (va_list);
1145
extern void tui_vUpdateSourceWindowsWithLine (va_list);
1146
 
1147
      /* Regardless of whether we can open the file,
1148
         set current_source_symtab. */
1149
      current_source_symtab = s;
1150
      current_source_line = line;
1151
      first_line_listed = line;
1152
 
1153
      /* make sure that the source window is displayed */
1154
      tuiDo ((TuiOpaqueFuncPtr) tui_vAddWinToLayout, SRC_WIN);
1155
 
1156
      tuiDo ((TuiOpaqueFuncPtr) tui_vUpdateSourceWindowsWithLine, s, line);
1157
      tuiDo ((TuiOpaqueFuncPtr) tui_vUpdateLocatorFilename, s->filename);
1158
    }
1159
#else
1160
  print_source_lines_base (s, line, stopline, noerror);
1161
#endif
1162
}
1163
 
1164
 
1165
 
1166
/* Print a list of files and line numbers which a user may choose from
1167
   in order to list a function which was specified ambiguously (as with
1168
   `list classname::overloadedfuncname', for example).  The vector in
1169
   SALS provides the filenames and line numbers.  */
1170
 
1171
static void
1172
ambiguous_line_spec (struct symtabs_and_lines *sals)
1173
{
1174
  int i;
1175
 
1176
  for (i = 0; i < sals->nelts; ++i)
1177
    printf_filtered ("file: \"%s\", line number: %d\n",
1178
                     sals->sals[i].symtab->filename, sals->sals[i].line);
1179
}
1180
 
1181
static void
1182
list_command (char *arg, int from_tty)
1183
{
1184
  struct symtabs_and_lines sals, sals_end;
1185
  struct symtab_and_line sal, sal_end;
1186
  struct symbol *sym;
1187
  char *arg1;
1188
  int no_end = 1;
1189
  int dummy_end = 0;
1190
  int dummy_beg = 0;
1191
  int linenum_beg = 0;
1192
  char *p;
1193
 
1194
  if (!have_full_symbols () && !have_partial_symbols ())
1195
    error ("No symbol table is loaded.  Use the \"file\" command.");
1196
 
1197
  /* Pull in a current source symtab if necessary */
1198
  if (current_source_symtab == 0 &&
1199
      (arg == 0 || arg[0] == '+' || arg[0] == '-'))
1200
    select_source_symtab (0);
1201
 
1202
  /* "l" or "l +" lists next ten lines.  */
1203
 
1204
  if (arg == 0 || STREQ (arg, "+"))
1205
    {
1206
      if (current_source_symtab == 0)
1207
        error ("No default source file yet.  Do \"help list\".");
1208
      print_source_lines (current_source_symtab, current_source_line,
1209
                          current_source_line + lines_to_list, 0);
1210
      return;
1211
    }
1212
 
1213
  /* "l -" lists previous ten lines, the ones before the ten just listed.  */
1214
  if (STREQ (arg, "-"))
1215
    {
1216
      if (current_source_symtab == 0)
1217
        error ("No default source file yet.  Do \"help list\".");
1218
      print_source_lines (current_source_symtab,
1219
                          max (first_line_listed - lines_to_list, 1),
1220
                          first_line_listed, 0);
1221
      return;
1222
    }
1223
 
1224
  /* Now if there is only one argument, decode it in SAL
1225
     and set NO_END.
1226
     If there are two arguments, decode them in SAL and SAL_END
1227
     and clear NO_END; however, if one of the arguments is blank,
1228
     set DUMMY_BEG or DUMMY_END to record that fact.  */
1229
 
1230
  arg1 = arg;
1231
  if (*arg1 == ',')
1232
    dummy_beg = 1;
1233
  else
1234
    {
1235
      sals = decode_line_1 (&arg1, 0, 0, 0, 0);
1236
 
1237
      if (!sals.nelts)
1238
        return;                 /*  C++  */
1239
      if (sals.nelts > 1)
1240
        {
1241
          ambiguous_line_spec (&sals);
1242
          xfree (sals.sals);
1243
          return;
1244
        }
1245
 
1246
      sal = sals.sals[0];
1247
      xfree (sals.sals);
1248
    }
1249
 
1250
  /* Record whether the BEG arg is all digits.  */
1251
 
1252
  for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
1253
  linenum_beg = (p == arg1);
1254
 
1255
  while (*arg1 == ' ' || *arg1 == '\t')
1256
    arg1++;
1257
  if (*arg1 == ',')
1258
    {
1259
      no_end = 0;
1260
      arg1++;
1261
      while (*arg1 == ' ' || *arg1 == '\t')
1262
        arg1++;
1263
      if (*arg1 == 0)
1264
        dummy_end = 1;
1265
      else
1266
        {
1267
          if (dummy_beg)
1268
            sals_end = decode_line_1 (&arg1, 0, 0, 0, 0);
1269
          else
1270
            sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0);
1271
          if (sals_end.nelts == 0)
1272
            return;
1273
          if (sals_end.nelts > 1)
1274
            {
1275
              ambiguous_line_spec (&sals_end);
1276
              xfree (sals_end.sals);
1277
              return;
1278
            }
1279
          sal_end = sals_end.sals[0];
1280
          xfree (sals_end.sals);
1281
        }
1282
    }
1283
 
1284
  if (*arg1)
1285
    error ("Junk at end of line specification.");
1286
 
1287
  if (!no_end && !dummy_beg && !dummy_end
1288
      && sal.symtab != sal_end.symtab)
1289
    error ("Specified start and end are in different files.");
1290
  if (dummy_beg && dummy_end)
1291
    error ("Two empty args do not say what lines to list.");
1292
 
1293
  /* if line was specified by address,
1294
     first print exactly which line, and which file.
1295
     In this case, sal.symtab == 0 means address is outside
1296
     of all known source files, not that user failed to give a filename.  */
1297
  if (*arg == '*')
1298
    {
1299
      if (sal.symtab == 0)
1300
        /* FIXME-32x64--assumes sal.pc fits in long.  */
1301
        error ("No source file for address %s.",
1302
               local_hex_string ((unsigned long) sal.pc));
1303
      sym = find_pc_function (sal.pc);
1304
      if (sym)
1305
        {
1306
          print_address_numeric (sal.pc, 1, gdb_stdout);
1307
          printf_filtered (" is in ");
1308
          fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
1309
          printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
1310
        }
1311
      else
1312
        {
1313
          print_address_numeric (sal.pc, 1, gdb_stdout);
1314
          printf_filtered (" is at %s:%d.\n",
1315
                           sal.symtab->filename, sal.line);
1316
        }
1317
    }
1318
 
1319
  /* If line was not specified by just a line number,
1320
     and it does not imply a symtab, it must be an undebuggable symbol
1321
     which means no source code.  */
1322
 
1323
  if (!linenum_beg && sal.symtab == 0)
1324
    error ("No line number known for %s.", arg);
1325
 
1326
  /* If this command is repeated with RET,
1327
     turn it into the no-arg variant.  */
1328
 
1329
  if (from_tty)
1330
    *arg = 0;
1331
 
1332
  if (dummy_beg && sal_end.symtab == 0)
1333
    error ("No default source file yet.  Do \"help list\".");
1334
  if (dummy_beg)
1335
    print_source_lines (sal_end.symtab,
1336
                        max (sal_end.line - (lines_to_list - 1), 1),
1337
                        sal_end.line + 1, 0);
1338
  else if (sal.symtab == 0)
1339
    error ("No default source file yet.  Do \"help list\".");
1340
  else if (no_end)
1341
    {
1342
      int first_line = sal.line - lines_to_list / 2;
1343
 
1344
      if (first_line < 1) first_line = 1;
1345
 
1346
      print_source_lines (sal.symtab, first_line, first_line + lines_to_list,
1347
                          0);
1348
    }
1349
  else
1350
    print_source_lines (sal.symtab, sal.line,
1351
                        (dummy_end
1352
                         ? sal.line + lines_to_list
1353
                         : sal_end.line + 1),
1354
                        0);
1355
}
1356
 
1357
/* Print info on range of pc's in a specified line.  */
1358
 
1359
static void
1360
line_info (char *arg, int from_tty)
1361
{
1362
  struct symtabs_and_lines sals;
1363
  struct symtab_and_line sal;
1364
  CORE_ADDR start_pc, end_pc;
1365
  int i;
1366
 
1367
  INIT_SAL (&sal);              /* initialize to zeroes */
1368
 
1369
  if (arg == 0)
1370
    {
1371
      sal.symtab = current_source_symtab;
1372
      sal.line = last_line_listed;
1373
      sals.nelts = 1;
1374
      sals.sals = (struct symtab_and_line *)
1375
        xmalloc (sizeof (struct symtab_and_line));
1376
      sals.sals[0] = sal;
1377
    }
1378
  else
1379
    {
1380
      sals = decode_line_spec_1 (arg, 0);
1381
 
1382
      dont_repeat ();
1383
    }
1384
 
1385
  /* C++  More than one line may have been specified, as when the user
1386
     specifies an overloaded function name. Print info on them all. */
1387
  for (i = 0; i < sals.nelts; i++)
1388
    {
1389
      sal = sals.sals[i];
1390
 
1391
      if (sal.symtab == 0)
1392
        {
1393
          printf_filtered ("No line number information available");
1394
          if (sal.pc != 0)
1395
            {
1396
              /* This is useful for "info line *0x7f34".  If we can't tell the
1397
                 user about a source line, at least let them have the symbolic
1398
                 address.  */
1399
              printf_filtered (" for address ");
1400
              wrap_here ("  ");
1401
              print_address (sal.pc, gdb_stdout);
1402
            }
1403
          else
1404
            printf_filtered (".");
1405
          printf_filtered ("\n");
1406
        }
1407
      else if (sal.line > 0
1408
               && find_line_pc_range (sal, &start_pc, &end_pc))
1409
        {
1410
          if (start_pc == end_pc)
1411
            {
1412
              printf_filtered ("Line %d of \"%s\"",
1413
                               sal.line, sal.symtab->filename);
1414
              wrap_here ("  ");
1415
              printf_filtered (" is at address ");
1416
              print_address (start_pc, gdb_stdout);
1417
              wrap_here ("  ");
1418
              printf_filtered (" but contains no code.\n");
1419
            }
1420
          else
1421
            {
1422
              printf_filtered ("Line %d of \"%s\"",
1423
                               sal.line, sal.symtab->filename);
1424
              wrap_here ("  ");
1425
              printf_filtered (" starts at address ");
1426
              print_address (start_pc, gdb_stdout);
1427
              wrap_here ("  ");
1428
              printf_filtered (" and ends at ");
1429
              print_address (end_pc, gdb_stdout);
1430
              printf_filtered (".\n");
1431
            }
1432
 
1433
          /* x/i should display this line's code.  */
1434
          set_next_address (start_pc);
1435
 
1436
          /* Repeating "info line" should do the following line.  */
1437
          last_line_listed = sal.line + 1;
1438
 
1439
          /* If this is the only line, show the source code.  If it could
1440
             not find the file, don't do anything special.  */
1441
          if (annotation_level && sals.nelts == 1)
1442
            identify_source_line (sal.symtab, sal.line, 0, start_pc);
1443
        }
1444
      else
1445
        /* Is there any case in which we get here, and have an address
1446
           which the user would want to see?  If we have debugging symbols
1447
           and no line numbers?  */
1448
        printf_filtered ("Line number %d is out of range for \"%s\".\n",
1449
                         sal.line, sal.symtab->filename);
1450
    }
1451
  xfree (sals.sals);
1452
}
1453
 
1454
/* Commands to search the source file for a regexp.  */
1455
 
1456
/* ARGSUSED */
1457
static void
1458
forward_search_command (char *regex, int from_tty)
1459
{
1460
  register int c;
1461
  register int desc;
1462
  register FILE *stream;
1463
  int line;
1464
  char *msg;
1465
 
1466
#if defined(TUI)
1467
  /*
1468
     ** If this is the TUI, search from the first line displayed in
1469
     ** the source window, otherwise, search from last_line_listed+1
1470
     ** in current_source_symtab
1471
   */
1472
  if (!tui_version)
1473
    line = last_line_listed;
1474
  else
1475
    {
1476
      if (srcWin->generic.isVisible && srcWin->generic.contentSize > 0)
1477
        line = ((TuiWinContent)
1478
         srcWin->generic.content)[0]->whichElement.source.lineOrAddr.lineNo;
1479
      else
1480
        {
1481
          printf_filtered ("No source displayed.\nExpression not found.\n");
1482
          return;
1483
        }
1484
    }
1485
  line++;
1486
#else
1487
  line = last_line_listed + 1;
1488
#endif
1489
 
1490
  msg = (char *) re_comp (regex);
1491
  if (msg)
1492
    error (msg);
1493
 
1494
  if (current_source_symtab == 0)
1495
    select_source_symtab (0);
1496
 
1497
  desc = open_source_file (current_source_symtab);
1498
  if (desc < 0)
1499
    perror_with_name (current_source_symtab->filename);
1500
 
1501
  if (current_source_symtab->line_charpos == 0)
1502
    find_source_lines (current_source_symtab, desc);
1503
 
1504
  if (line < 1 || line > current_source_symtab->nlines)
1505
    {
1506
      close (desc);
1507
      error ("Expression not found");
1508
    }
1509
 
1510
  if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
1511
    {
1512
      close (desc);
1513
      perror_with_name (current_source_symtab->filename);
1514
    }
1515
 
1516
  stream = fdopen (desc, FDOPEN_MODE);
1517
  clearerr (stream);
1518
  while (1)
1519
    {
1520
      static char *buf = NULL;
1521
      register char *p;
1522
      int cursize, newsize;
1523
 
1524
      cursize = 256;
1525
      buf = xmalloc (cursize);
1526
      p = buf;
1527
 
1528
      c = getc (stream);
1529
      if (c == EOF)
1530
        break;
1531
      do
1532
        {
1533
          *p++ = c;
1534
          if (p - buf == cursize)
1535
            {
1536
              newsize = cursize + cursize / 2;
1537
              buf = xrealloc (buf, newsize);
1538
              p = buf + cursize;
1539
              cursize = newsize;
1540
            }
1541
        }
1542
      while (c != '\n' && (c = getc (stream)) >= 0);
1543
 
1544
#ifdef CRLF_SOURCE_FILES
1545
      /* Remove the \r, if any, at the end of the line, otherwise
1546
         regular expressions that end with $ or \n won't work.  */
1547
      if (p - buf > 1 && p[-2] == '\r')
1548
        {
1549
          p--;
1550
          p[-1] = '\n';
1551
        }
1552
#endif
1553
 
1554
      /* we now have a source line in buf, null terminate and match */
1555
      *p = 0;
1556
      if (re_exec (buf) > 0)
1557
        {
1558
          /* Match! */
1559
          fclose (stream);
1560
          if (tui_version)
1561
            print_source_lines_base (current_source_symtab, line, line + 1, 0);
1562
          print_source_lines (current_source_symtab, line, line + 1, 0);
1563
          set_internalvar (lookup_internalvar ("_"),
1564
                           value_from_longest (builtin_type_int,
1565
                                               (LONGEST) line));
1566
          current_source_line = max (line - lines_to_list / 2, 1);
1567
          return;
1568
        }
1569
      line++;
1570
    }
1571
 
1572
  printf_filtered ("Expression not found\n");
1573
  fclose (stream);
1574
}
1575
 
1576
/* ARGSUSED */
1577
static void
1578
reverse_search_command (char *regex, int from_tty)
1579
{
1580
  register int c;
1581
  register int desc;
1582
  register FILE *stream;
1583
  int line;
1584
  char *msg;
1585
#if defined(TUI)
1586
  /*
1587
     ** If this is the TUI, search from the first line displayed in
1588
     ** the source window, otherwise, search from last_line_listed-1
1589
     ** in current_source_symtab
1590
   */
1591
  if (!tui_version)
1592
    line = last_line_listed;
1593
  else
1594
    {
1595
      if (srcWin->generic.isVisible && srcWin->generic.contentSize > 0)
1596
        line = ((TuiWinContent)
1597
         srcWin->generic.content)[0]->whichElement.source.lineOrAddr.lineNo;
1598
      else
1599
        {
1600
          printf_filtered ("No source displayed.\nExpression not found.\n");
1601
          return;
1602
        }
1603
    }
1604
  line--;
1605
#else
1606
  line = last_line_listed - 1;
1607
#endif
1608
 
1609
  msg = (char *) re_comp (regex);
1610
  if (msg)
1611
    error (msg);
1612
 
1613
  if (current_source_symtab == 0)
1614
    select_source_symtab (0);
1615
 
1616
  desc = open_source_file (current_source_symtab);
1617
  if (desc < 0)
1618
    perror_with_name (current_source_symtab->filename);
1619
 
1620
  if (current_source_symtab->line_charpos == 0)
1621
    find_source_lines (current_source_symtab, desc);
1622
 
1623
  if (line < 1 || line > current_source_symtab->nlines)
1624
    {
1625
      close (desc);
1626
      error ("Expression not found");
1627
    }
1628
 
1629
  if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
1630
    {
1631
      close (desc);
1632
      perror_with_name (current_source_symtab->filename);
1633
    }
1634
 
1635
  stream = fdopen (desc, FDOPEN_MODE);
1636
  clearerr (stream);
1637
  while (line > 1)
1638
    {
1639
/* FIXME!!!  We walk right off the end of buf if we get a long line!!! */
1640
      char buf[4096];           /* Should be reasonable??? */
1641
      register char *p = buf;
1642
 
1643
      c = getc (stream);
1644
      if (c == EOF)
1645
        break;
1646
      do
1647
        {
1648
          *p++ = c;
1649
        }
1650
      while (c != '\n' && (c = getc (stream)) >= 0);
1651
 
1652
#ifdef CRLF_SOURCE_FILES
1653
      /* Remove the \r, if any, at the end of the line, otherwise
1654
         regular expressions that end with $ or \n won't work.  */
1655
      if (p - buf > 1 && p[-2] == '\r')
1656
        {
1657
          p--;
1658
          p[-1] = '\n';
1659
        }
1660
#endif
1661
 
1662
      /* We now have a source line in buf; null terminate and match.  */
1663
      *p = 0;
1664
      if (re_exec (buf) > 0)
1665
        {
1666
          /* Match! */
1667
          fclose (stream);
1668
          if (tui_version)
1669
            print_source_lines_base (current_source_symtab, line, line + 1, 0);
1670
          print_source_lines (current_source_symtab, line, line + 1, 0);
1671
          set_internalvar (lookup_internalvar ("_"),
1672
                           value_from_longest (builtin_type_int,
1673
                                               (LONGEST) line));
1674
          current_source_line = max (line - lines_to_list / 2, 1);
1675
          return;
1676
        }
1677
      line--;
1678
      if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
1679
        {
1680
          fclose (stream);
1681
          perror_with_name (current_source_symtab->filename);
1682
        }
1683
    }
1684
 
1685
  printf_filtered ("Expression not found\n");
1686
  fclose (stream);
1687
  return;
1688
}
1689
 
1690
void
1691
_initialize_source (void)
1692
{
1693
  struct cmd_list_element *c;
1694
  current_source_symtab = 0;
1695
  init_source_path ();
1696
 
1697
  /* The intention is to use POSIX Basic Regular Expressions.
1698
     Always use the GNU regex routine for consistency across all hosts.
1699
     Our current GNU regex.c does not have all the POSIX features, so this is
1700
     just an approximation.  */
1701
  re_set_syntax (RE_SYNTAX_GREP);
1702
 
1703
  c = add_cmd ("directory", class_files, directory_command,
1704
               "Add directory DIR to beginning of search path for source files.\n\
1705
Forget cached info on source file locations and line positions.\n\
1706
DIR can also be $cwd for the current working directory, or $cdir for the\n\
1707
directory in which the source file was compiled into object code.\n\
1708
With no argument, reset the search path to $cdir:$cwd, the default.",
1709
               &cmdlist);
1710
 
1711
  if (dbx_commands)
1712
    add_com_alias ("use", "directory", class_files, 0);
1713
 
1714
  c->completer = filename_completer;
1715
 
1716
  add_cmd ("directories", no_class, show_directories,
1717
           "Current search path for finding source files.\n\
1718
$cwd in the path means the current working directory.\n\
1719
$cdir in the path means the compilation directory of the source file.",
1720
           &showlist);
1721
 
1722
  if (xdb_commands)
1723
    {
1724
      add_com_alias ("D", "directory", class_files, 0);
1725
      add_cmd ("ld", no_class, show_directories,
1726
               "Current search path for finding source files.\n\
1727
$cwd in the path means the current working directory.\n\
1728
$cdir in the path means the compilation directory of the source file.",
1729
               &cmdlist);
1730
    }
1731
 
1732
  add_info ("source", source_info,
1733
            "Information about the current source file.");
1734
 
1735
  add_info ("line", line_info,
1736
            concat ("Core addresses of the code for a source line.\n\
1737
Line can be specified as\n\
1738
  LINENUM, to list around that line in current file,\n\
1739
  FILE:LINENUM, to list around that line in that file,\n\
1740
  FUNCTION, to list around beginning of that function,\n\
1741
  FILE:FUNCTION, to distinguish among like-named static functions.\n\
1742
", "\
1743
Default is to describe the last source line that was listed.\n\n\
1744
This sets the default address for \"x\" to the line's first instruction\n\
1745
so that \"x/i\" suffices to start examining the machine code.\n\
1746
The address is also stored as the value of \"$_\".", NULL));
1747
 
1748
  add_com ("forward-search", class_files, forward_search_command,
1749
           "Search for regular expression (see regex(3)) from last line listed.\n\
1750
The matching line number is also stored as the value of \"$_\".");
1751
  add_com_alias ("search", "forward-search", class_files, 0);
1752
 
1753
  add_com ("reverse-search", class_files, reverse_search_command,
1754
           "Search backward for regular expression (see regex(3)) from last line listed.\n\
1755
The matching line number is also stored as the value of \"$_\".");
1756
 
1757
  if (xdb_commands)
1758
    {
1759
      add_com_alias ("/", "forward-search", class_files, 0);
1760
      add_com_alias ("?", "reverse-search", class_files, 0);
1761
    }
1762
 
1763
  add_com ("list", class_files, list_command,
1764
           concat ("List specified function or line.\n\
1765
With no argument, lists ten more lines after or around previous listing.\n\
1766
\"list -\" lists the ten lines before a previous ten-line listing.\n\
1767
One argument specifies a line, and ten lines are listed around that line.\n\
1768
Two arguments with comma between specify starting and ending lines to list.\n\
1769
", "\
1770
Lines can be specified in these ways:\n\
1771
  LINENUM, to list around that line in current file,\n\
1772
  FILE:LINENUM, to list around that line in that file,\n\
1773
  FUNCTION, to list around beginning of that function,\n\
1774
  FILE:FUNCTION, to distinguish among like-named static functions.\n\
1775
  *ADDRESS, to list around the line containing that address.\n\
1776
With two args if one is empty it stands for ten lines away from the other arg.", NULL));
1777
 
1778
  if (!xdb_commands)
1779
    add_com_alias ("l", "list", class_files, 1);
1780
  else
1781
    add_com_alias ("v", "list", class_files, 1);
1782
 
1783
  if (dbx_commands)
1784
    add_com_alias ("file", "list", class_files, 1);
1785
 
1786
  add_show_from_set
1787
    (add_set_cmd ("listsize", class_support, var_uinteger,
1788
                  (char *) &lines_to_list,
1789
                  "Set number of source lines gdb will list by default.",
1790
                  &setlist),
1791
     &showlist);
1792
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.