📄 utils.c
字号:
lineptr++; } if (chars_printed >= chars_per_line) { unsigned int save_chars = chars_printed; chars_printed = 0; lines_printed++; /* If we aren't actually wrapping, don't output newline -- if chars_per_line is right, we probably just overflowed anyway; if it's wrong, let us keep going. */ if (wrap_column) putc ('\n', stream); /* Possible new page. */ if (lines_printed >= lines_per_page - 1) prompt_for_continue (); /* Now output indentation and wrapped string */ if (wrap_column) { if (wrap_indent) fputs (wrap_indent, stream); *wrap_pointer = '\0'; /* Null-terminate saved stuff */ fputs (wrap_buffer, stream); /* and eject it */ /* FIXME, this strlen is what prevents wrap_indent from containing tabs. However, if we recurse to print it and count its chars, we risk trouble if wrap_indent is longer than (the user settable) chars_per_line. Note also that this can set chars_printed > chars_per_line if we are printing a long string. */ chars_printed = strlen (wrap_indent) + (save_chars - wrap_column); wrap_pointer = wrap_buffer; /* Reset buffer */ wrap_buffer[0] = '\0'; wrap_column = 0; /* And disable fancy wrap */ } } } if (*lineptr == '\n') { chars_printed = 0; wrap_here ((char *)0); /* Spit out chars, cancel further wraps */ lines_printed++; putc ('\n', stream); lineptr++; } }}/* fputs_demangled is a variant of fputs_filtered that demangles g++ names.*/voidfputs_demangled (linebuffer, stream, arg_mode) char *linebuffer; FILE *stream; int arg_mode;{#define SYMBOL_MAX 1024#define SYMBOL_CHAR(c) (isascii(c) \ && (isalnum(c) || (c) == '_' || (c) == CPLUS_MARKER)) char buf[SYMBOL_MAX+1];# define DMSLOP 5 /* How much room to leave in buf */ char *p; if (linebuffer == NULL) return; /* If user wants to see raw output, no problem. */ if (!demangle) { fputs_filtered (linebuffer, stream); return; } p = linebuffer; while ( *p != (char) 0 ) { int i = 0; /* collect non-interesting characters into buf */ while (*p != (char) 0 && !SYMBOL_CHAR(*p) && i < (int)sizeof(buf)-DMSLOP ) { buf[i++] = *p; p++; } if (i > 0) { /* output the non-interesting characters without demangling */ buf[i] = (char) 0; fputs_filtered(buf, stream); i = 0; /* reset buf */ } /* and now the interesting characters */ while (i < SYMBOL_MAX && *p != (char) 0 && SYMBOL_CHAR(*p) && i < (int)sizeof(buf) - DMSLOP) { buf[i++] = *p; p++; } buf[i] = (char) 0; if (i > 0) { char * result; if ( (result = cplus_demangle(buf, arg_mode)) != NULL ) { fputs_filtered(result, stream); free(result); } else { fputs_filtered(buf, stream); } } }}/* Print a variable number of ARGS using format FORMAT. If this information is going to put the amount written (since the last call to REINITIALIZE_MORE_FILTER or the last page break) over the page size, print out a pause message and do a gdb_readline to get the users permision to continue. Unlike fprintf, this function does not return a value. We implement three variants, vfprintf (takes a vararg list and stream), fprintf (takes a stream to write on), and printf (the usual). Note that this routine has a restriction that the length of the final output line must be less than 255 characters *or* it must be less than twice the size of the format string. This is a very arbitrary restriction, but it is an internal restriction, so I'll put it in. This means that the %s format specifier is almost useless; unless the caller can GUARANTEE that the string is short enough, fputs_filtered should be used instead. Note also that a longjmp to top level may occur in this routine (since prompt_for_continue may do so) so this routine should not be called when cleanups are not in place. */#define MIN_LINEBUF 255voidvfprintf_filtered (stream, format, args) FILE *stream; char *format; va_list args;{ char line_buf[MIN_LINEBUF+10]; char *linebuffer = line_buf; int format_length; format_length = strlen (format); /* Reallocate buffer to a larger size if this is necessary. */ if (format_length * 2 > MIN_LINEBUF) { linebuffer = alloca (10 + format_length * 2); } /* This won't blow up if the restrictions described above are followed. */ vsprintf (linebuffer, format, args); fputs_filtered (linebuffer, stream);}/* VARARGS */voidfprintf_filtered (va_alist) va_dcl{ va_list args; FILE *stream; char *format; va_start (args); stream = va_arg (args, FILE *); format = va_arg (args, char *); /* This won't blow up if the restrictions described above are followed. */ vfprintf_filtered (stream, format, args); va_end (args);}/* Like fprintf_filtered, but prints it's result indent. Called as fprintfi_filtered (spaces, format, arg1, arg2, ...); *//* VARARGS */voidfprintfi_filtered (va_alist) va_dcl{ va_list args; int spaces; FILE *stream; char *format; va_start (args); spaces = va_arg (args, int); stream = va_arg (args, FILE *); format = va_arg (args, char *); print_spaces_filtered (spaces, stream); /* This won't blow up if the restrictions described above are followed. */ vfprintf_filtered (stream, format, args); va_end (args);}/* VARARGS */voidprintf_filtered (va_alist) va_dcl{ va_list args; char *format; va_start (args); format = va_arg (args, char *); vfprintf_filtered (stdout, format, args); va_end (args);}/* Like printf_filtered, but prints it's result indented. Called as printfi_filtered (spaces, format, arg1, arg2, ...); *//* VARARGS */voidprintfi_filtered (va_alist) va_dcl{ va_list args; int spaces; char *format; va_start (args); spaces = va_arg (args, int); format = va_arg (args, char *); print_spaces_filtered (spaces, stdout); vfprintf_filtered (stdout, format, args); va_end (args);}/* Easy -- but watch out! This routine is *not* a replacement for puts()! puts() appends a newline. This one doesn't, and had better not! */voidputs_filtered (string) char *string;{ fputs_filtered (string, stdout);}/* Return a pointer to N spaces and a null. The pointer is good until the next call to here. */char *n_spaces (n) int n;{ register char *t; static char *spaces; static int max_spaces; if (n > max_spaces) { if (spaces) free (spaces); spaces = (char *) xmalloc (n+1); for (t = spaces+n; t != spaces;) *--t = ' '; spaces[n] = '\0'; max_spaces = n; } return spaces + max_spaces - n;}/* Print N spaces. */voidprint_spaces_filtered (n, stream) int n; FILE *stream;{ fputs_filtered (n_spaces (n), stream);}/* C++ demangler stuff. *//* Make a copy of a symbol, applying C++ demangling if demangling is enabled and a demangled version exists. Note that the value returned from cplus_demangle is already allocated in malloc'd memory. */char *strdup_demangled (name) const char *name;{ char *demangled = NULL; if (demangle) { demangled = cplus_demangle (name, DMGL_PARAMS | DMGL_ANSI); } return ((demangled != NULL) ? demangled : strdup (name));}/* Print NAME on STREAM, demangling if necessary. */voidfprint_symbol (stream, name) FILE *stream; char *name;{ char *demangled; if ((!demangle) || NULL == (demangled = cplus_demangle (name, DMGL_PARAMS | DMGL_ANSI))) fputs_filtered (name, stream); else { fputs_filtered (demangled, stream); free (demangled); }}/* Do a strcmp() type operation on STRING1 and STRING2, ignoring any differences in whitespace. Returns 0 if they match, non-zero if they don't (slightly different than strcmp()'s range of return values). As an extra hack, string1=="FOO(ARGS)" matches string2=="FOO". This "feature" is useful for demangle_and_match(), which is used when searching for matching C++ function names (such as if the user types 'break FOO', where FOO is a mangled C++ function). */intstrcmp_iw (string1, string2) const char *string1; const char *string2;{ while ((*string1 != '\0') && (*string2 != '\0')) { while (isspace (*string1)) { string1++; } while (isspace (*string2)) { string2++; } if (*string1 != *string2) { break; } if (*string1 != '\0') { string1++; string2++; } } return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0');}/* Demangle NAME and compare the result with LOOKFOR, ignoring any differences in whitespace. If a match is found, returns a pointer to the demangled version of NAME in malloc'd memory, which needs to be freed by the caller after use. If a match is not found, returns NULL. OPTIONS is a flags word that controls the demangling process and is just passed on to the demangler. When the caller sees a non-NULL result, it knows that NAME is the mangled equivalent of LOOKFOR, and it can use either NAME, the "official demangled" version of NAME (the return value) or the "unofficial demangled" version of NAME (LOOKFOR, which it already knows). */char *demangle_and_match (name, lookfor, options) const char *name; const char *lookfor; int options;{ char *demangled; if ((demangled = cplus_demangle (name, options)) != NULL) { if (strcmp_iw (demangled, lookfor) != 0) { free (demangled); demangled = NULL; } } return (demangled);}#ifdef TIOCGWINSZ#ifdef SIGWINCHstatic voidsigwinch(){ struct winsize win; if (ioctl(0, TIOCGWINSZ, (char *)&win) < 0) { perror("TIOCGWINSZ"); return; } lines_per_page = win.ws_row; chars_per_line = win.ws_col;}#ifndef SIGWINCH_HANDLER#define SIGWINCH_HANDLER sigwinch#endif#endiftermdim(){ SIGWINCH_HANDLER();#ifdef SIGWINCH signal(SIGWINCH, SIGWINCH_HANDLER);#endif}#else/* Initialize the screen height and width from termcap. */termdim(){ register int v; register char *cp; /* 2048 is large enough for all known terminals, according to the GNU termcap manual. */ char term_buffer[2048]; if ((termtype = getenv ("TERM")) == 0 || tgetent(term_buffer, cp) <= 0) return; v = tgetnum("li"); if (v >= 0) lines_per_page = v; else /* The number of lines per page is not mentioned in the terminal description. This probably means that paging is not useful (e.g. emacs shell window), so disable paging. */ lines_per_page = UINT_MAX; v = tgetnum("co"); if (v >= 0) chars_per_line = v;}#endifvoid_initialize_utils (){ struct cmd_list_element *c; c = add_set_cmd ("width", class_support, var_uinteger, (char *)&chars_per_line, "Set number of characters gdb thinks are in a line.", &setlist); add_show_from_set (c, &showlist); c->function.sfunc = set_width_command; add_show_from_set (add_set_cmd ("height", class_support, var_uinteger, (char *)&lines_per_page, "Set number of lines gdb thinks are in a page.", &setlist), &showlist); /* These defaults will be used if we are unable to get the correct values from termcap. */#if defined(__GO32__) lines_per_page = ScreenRows(); chars_per_line = ScreenCols();#else lines_per_page = 24; chars_per_line = 80; termdim();#endif /* If the output is not a terminal, don't paginate it. */ if (!ISATTY (stdout)) lines_per_page = UINT_MAX; set_width_command ((char *)NULL, 0, c); add_show_from_set (add_set_cmd ("demangle", class_support, var_boolean, (char *)&demangle, "Set demangling of encoded C++ names when displaying symbols.", &setprintlist), &showprintlist); add_show_from_set (add_set_cmd ("sevenbit-strings", class_support, var_boolean, (char *)&sevenbit_strings, "Set printing of 8-bit characters in strings as \\nnn.", &setprintlist), &showprintlist); add_show_from_set (add_set_cmd ("asm-demangle", class_support, var_boolean, (char *)&asm_demangle, "Set demangling of C++ names in disassembly listings.", &setprintlist), &showprintlist);}/* Machine specific function to handle SIGWINCH signal. */#ifdef SIGWINCH_HANDLER_BODY SIGWINCH_HANDLER_BODY#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -