Annotation of 43BSDReno/contrib/emacs-18.55/gdb/source.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.