?? source.c
字號(hào):
/* List lines of source files for GDB, the GNU debugger. Copyright (C) 1986, 1987, 1988, 1989, 1991 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <sys/param.h>#include "defs.h"#include "symtab.h"#include "expression.h"#include "language.h"#include "command.h"#include "gdbcmd.h"#include "frame.h"#ifdef USG#include <sys/types.h>#endif#include <string.h>#include <sys/stat.h>#include <fcntl.h>#include "gdbcore.h"#include "regex.h"#include "symfile.h"#include "objfiles.h"/* Prototypes for local functions. */static intopen_source_file PARAMS ((struct symtab *));intget_filename_and_charpos PARAMS ((struct symtab *, char **));static voidreverse_search_command PARAMS ((char *, int));static voidforward_search_command PARAMS ((char *, int));static voidline_info PARAMS ((char *, int));static voidlist_command PARAMS ((char *, int));static voidambiguous_line_spec PARAMS ((struct symtabs_and_lines *));static voidsource_info PARAMS ((char *, int));static voidshow_directories PARAMS ((char *, int));static voidfind_source_lines PARAMS ((struct symtab *, int));/* If we use this declaration, it breaks because of fucking ANSI "const" stuff on some systems. We just have to not declare it at all, have it default to int, and possibly botch on a few systems. Thanks, ANSIholes... *//* extern char *strstr(); *//* Path of directories to search for source files. Same format as the PATH environment variable's value. */char *source_path;/* Symtab of default file for listing lines of. */struct symtab *current_source_symtab;/* Default next line to list. */int current_source_line;/* Default number of lines to print with commands like "list". This is based on guessing how many long (i.e. more than chars_per_line characters) lines there will be. To be completely correct, "list" and friends should be rewritten to count characters and see where things are wrapping, but that would be a fair amount of work. */int lines_to_list = 10;/* Line number of last line printed. Default for various commands. current_source_line is usually, but not always, the same as this. */static int last_line_listed;/* First line number listed by last listing command. */static int first_line_listed;/* Set the source file default for the "list" command, specifying a symtab. Sigh. Behavior specification: If it is called with a non-zero argument, that is the symtab to select. If it is not, first lookup "main"; if it exists, use the symtab and line it defines. If not, take the last symtab in the symtab lists (if it exists) or the last symtab in the psymtab lists (if *it* exists). If none of this works, report an error. */voidselect_source_symtab (s) register struct symtab *s;{ struct symtabs_and_lines sals; struct symtab_and_line sal; struct partial_symtab *ps; struct partial_symtab *cs_pst = 0; struct objfile *ofp; if (s) { current_source_symtab = s; current_source_line = 1; return; } /* Make the default place to list be the function `main' if one exists. */ if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0, NULL)) { sals = decode_line_spec ("main", 1); sal = sals.sals[0]; free (sals.sals); current_source_symtab = sal.symtab; current_source_line = max (sal.line - (lines_to_list - 1), 1); if (current_source_symtab) return; } /* All right; find the last file in the symtab list (ignoring .h's). */ current_source_line = 1; for (ofp = object_files; ofp != NULL; ofp = ofp -> next) { for (s = ofp -> symtabs; s; s = s->next) { char *name = s -> filename; int len = strlen (name); if (! (len > 2 && (strcmp (&name[len - 2], ".h") == 0))) { current_source_symtab = s; } } } if (current_source_symtab) return; /* Howabout the partial symbol tables? */ for (ofp = object_files; ofp != NULL; ofp = ofp -> next) { for (ps = ofp -> psymtabs; ps != NULL; ps = ps -> next) { char *name = ps -> filename; int len = strlen (name); if (! (len > 2 && (strcmp (&name[len - 2], ".h") == 0))) { cs_pst = ps; } } } if (cs_pst) { if (cs_pst -> readin) { fatal ("Internal: select_source_symtab: readin pst found and no symtabs."); } else { current_source_symtab = PSYMTAB_TO_SYMTAB (cs_pst); } } if (current_source_symtab) return; error ("Can't find a default source file");}static voidshow_directories (ignore, from_tty) char *ignore; int from_tty;{ printf_filtered ("Source directories searched: %s\n", source_path);}/* Forget what we learned about line positions in source files, and which directories contain them; must check again now since files may be found in a different directory now. */voidforget_cached_source_info (){ register struct symtab *s; register struct objfile *objfile; for (objfile = object_files; objfile != NULL; objfile = objfile -> next) { for (s = objfile -> symtabs; s != NULL; s = s -> next) { if (s -> line_charpos != NULL) { mfree (objfile -> md, s -> line_charpos); s -> line_charpos = NULL; } if (s -> fullname != NULL) { mfree (objfile -> md, s -> fullname); s -> fullname = NULL; } } }}voidinit_source_path (){ source_path = savestring ("$cdir:$cwd", /* strlen of it */ 10); forget_cached_source_info ();}/* Add zero or more directories to the front of the source path. */ voiddirectory_command (dirname, from_tty) char *dirname; int from_tty;{ dont_repeat (); /* FIXME, this goes to "delete dir"... */ if (dirname == 0) { if (query ("Reinitialize source path to empty? ", "")) { free (source_path); init_source_path (); } } else mod_path (dirname, &source_path); if (from_tty) show_directories ((char *)0, from_tty); forget_cached_source_info ();}/* Add zero or more directories to the front of an arbitrary path. */voidmod_path (dirname, which_path) char *dirname; char **which_path;{ char *old = *which_path; int prefix = 0; if (dirname == 0) return; dirname = strsave (dirname); make_cleanup (free, dirname); do { char *name = dirname; register char *p; struct stat st; { char *colon = strchr (name, ':'); char *space = strchr (name, ' '); char *tab = strchr (name, '\t'); if (colon == 0 && space == 0 && tab == 0) p = dirname = name + strlen (name); else { p = 0; if (colon != 0 && (p == 0 || colon < p)) p = colon; if (space != 0 && (p == 0 || space < p)) p = space; if (tab != 0 && (p == 0 || tab < p)) p = tab; dirname = p + 1; while (*dirname == ':' || *dirname == ' ' || *dirname == '\t') ++dirname; } } if (p[-1] == '/') /* Sigh. "foo/" => "foo" */ --p; *p = '\0'; while (p[-1] == '.') { if (p - name == 1) { /* "." => getwd (). */ name = current_directory; goto append; } else if (p[-2] == '/') { if (p - name == 2) { /* "/." => "/". */ *--p = '\0'; goto append; } else { /* "...foo/." => "...foo". */ p -= 2; *p = '\0'; continue; } } else break; } if (name[0] == '~') name = tilde_expand (name); else if (name[0] != '/' && name[0] != '$') name = concat (current_directory, "/", name, NULL); else name = savestring (name, p - name); make_cleanup (free, name); /* Unless it's a variable, check existence. */ if (name[0] != '$') { if (stat (name, &st) < 0) perror_with_name (name); if ((st.st_mode & S_IFMT) != S_IFDIR) error ("%s is not a directory.", name); } append: { register unsigned int len = strlen (name); p = *which_path; while (1) { if (!strncmp (p, name, len) && (p[len] == '\0' || p[len] == ':')) { /* Found it in the search path, remove old copy */ if (p > *which_path) p--; /* Back over leading colon */ if (prefix > p - *which_path) goto skip_dup; /* Same dir twice in one cmd */ strcpy (p, &p[len+1]); /* Copy from next \0 or : */ } p = strchr (p, ':'); if (p != 0) ++p; else break; } if (p == 0) { /* 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. */ if (prefix) { char *temp, c; c = old[prefix]; old[prefix] = '\0'; temp = concat (old, ":", name, NULL); old[prefix] = c; *which_path = concat (temp, "", &old[prefix], NULL); prefix = strlen (temp); free (temp); } else { *which_path = concat (name, (old[0]? ":" : old), old, NULL); prefix = strlen (name); } free (old); old = *which_path; } } skip_dup: ; } while (*dirname != '\0');}static voidsource_info (ignore, from_tty) char *ignore; int from_tty;{ register struct symtab *s = current_source_symtab; if (!s) { printf_filtered("No current source file.\n"); return; } printf_filtered ("Current source file is %s\n", s->filename); if (s->dirname) printf_filtered ("Compilation directory is %s\n", s->dirname); if (s->fullname) printf_filtered ("Located in %s\n", s->fullname); if (s->nlines) printf_filtered ("Contains %d lines\n", s->nlines); printf_filtered("Source language %s.\n", language_str (s->language));}/* Open a file named STRING, searching path PATH (dir names sep by colons) using mode MODE and protection bits PROT in the calls to open. If TRY_CWD_FIRST, try to open ./STRING before searching PATH. (ie pretend the first element of PATH is ".") If FILENAMED_OPENED is non-null, set it to a newly allocated string naming the actual file opened (this string will always start with a "/". We have to take special pains to avoid doubling the "/" between the directory and the file, sigh! Emacs gets confuzzed by this when we print the source file name!!! If a file is found, return the descriptor. Otherwise, return -1, with errno set for the last name we tried to open. *//* >>>> This should only allow files of certain types, >>>> eg executable, non-directory */intopenp (path, try_cwd_first, string, mode, prot, filename_opened) char *path; int try_cwd_first; char *string; int mode; int prot; char **filename_opened;{ register int fd; register char *filename; register char *p, *p1; register int len; int alloclen; if (!path) path = "."; /* ./foo => foo */ while (string[0] == '.' && string[1] == '/') string += 2; if (try_cwd_first || string[0] == '/') { filename = string; fd = open (filename, mode, prot); if (fd >= 0 || string[0] == '/') goto done; } alloclen = strlen (path) + strlen (string) + 2; filename = (char *) alloca (alloclen); fd = -1; for (p = path; p; p = p1 ? p1 + 1 : 0) { p1 = (char *) strchr (p, ':'); if (p1) len = p1 - p; else len = strlen (p); if (len == 4 && p[0] == '$' && p[1] == 'c' && p[2] == 'w' && p[3] == 'd') {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -