📄 utils.c
字号:
else { fatal ("virtual memory exhausted."); }}/* Like mmalloc but get error if no storage available, and protect against the caller wanting to allocate zero bytes. Whether to return NULL for a zero byte request, or translate the request into a request for one byte of zero'd storage, is a religious issue. */PTRxmmalloc (md, size) PTR md; long size;{ register PTR val; if (size == 0) { val = NULL; } else if ((val = mmalloc (md, size)) == NULL) { nomem (size); } return (val);}/* Like mrealloc but get error if no storage available. */PTRxmrealloc (md, ptr, size) PTR md; PTR ptr; long size;{ register PTR val; if (ptr != NULL) { val = mrealloc (md, ptr, size); } else { val = mmalloc (md, size); } if (val == NULL) { nomem (size); } return (val);}/* Like malloc but get error if no storage available, and protect against the caller wanting to allocate zero bytes. */PTRxmalloc (size) long size;{ return (xmmalloc ((void *) NULL, size));}/* Like mrealloc but get error if no storage available. */PTRxrealloc (ptr, size) PTR ptr; long size;{ return (xmrealloc ((void *) NULL, ptr, size));}/* My replacement for the read system call. Used like `read' but keeps going if `read' returns too soon. */intmyread (desc, addr, len) int desc; char *addr; int len;{ register int val; int orglen = len; while (len > 0) { val = read (desc, addr, len); if (val < 0) return val; if (val == 0) return orglen - len; len -= val; addr += val; } return orglen;}/* Make a copy of the string at PTR with SIZE characters (and add a null character at the end in the copy). Uses malloc to get the space. Returns the address of the copy. */char *savestring (ptr, size) const char *ptr; int size;{ register char *p = (char *) xmalloc (size + 1); memcpy (p, ptr, size); p[size] = 0; return p;}char *msavestring (md, ptr, size) void *md; const char *ptr; int size;{ register char *p = (char *) xmmalloc (md, size + 1); memcpy (p, ptr, size); p[size] = 0; return p;}/* The "const" is so it compiles under DGUX (which prototypes strsave in <string.h>. FIXME: This should be named "xstrsave", shouldn't it? Doesn't real strsave return NULL if out of memory? */char *strsave (ptr) const char *ptr;{ return savestring (ptr, strlen (ptr));}char *mstrsave (md, ptr) void *md; const char *ptr;{ return (msavestring (md, ptr, strlen (ptr)));}voidprint_spaces (n, file) register int n; register FILE *file;{ while (n-- > 0) fputc (' ', file);}/* Ask user a y-or-n question and return 1 iff answer is yes. Takes three args which are given to printf to print the question. The first, a control string, should end in "? ". It should not say how to answer, because we do that. *//* VARARGS */intquery (va_alist) va_dcl{ va_list args; char *ctlstr; register int answer; register int ans2; /* Automatically answer "yes" if input is not from a terminal. */ if (!input_from_terminal_p ()) return 1; while (1) { wrap_here (""); /* Flush any buffered output */ fflush (stdout); va_start (args); ctlstr = va_arg (args, char *); vfprintf_filtered (stdout, ctlstr, args); va_end (args); printf_filtered ("(y or n) "); fflush (stdout); answer = fgetc (stdin); clearerr (stdin); /* in case of C-d */ if (answer == EOF) /* C-d */ return 1; if (answer != '\n') /* Eat rest of input line, to EOF or newline */ do { ans2 = fgetc (stdin); clearerr (stdin); } while (ans2 != EOF && ans2 != '\n'); if (answer >= 'a') answer -= 040; if (answer == 'Y') return 1; if (answer == 'N') return 0; printf_filtered ("Please answer y or n.\n"); }}/* Parse a C escape sequence. STRING_PTR points to a variable containing a pointer to the string to parse. That pointer should point to the character after the \. That pointer is updated past the characters we use. The value of the escape sequence is returned. A negative value means the sequence \ newline was seen, which is supposed to be equivalent to nothing at all. If \ is followed by a null character, we return a negative value and leave the string pointer pointing at the null character. If \ is followed by 000, we return 0 and leave the string pointer after the zeros. A value of 0 does not mean end of string. */intparse_escape (string_ptr) char **string_ptr;{ register int c = *(*string_ptr)++; switch (c) { case 'a': return 007; /* Bell (alert) char */ case 'b': return '\b'; case 'e': /* Escape character */ return 033; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case 'v': return '\v'; case '\n': return -2; case 0: (*string_ptr)--; return 0; case '^': c = *(*string_ptr)++; if (c == '\\') c = parse_escape (string_ptr); if (c == '?') return 0177; return (c & 0200) | (c & 037); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { register int i = c - '0'; register int count = 0; while (++count < 3) { if ((c = *(*string_ptr)++) >= '0' && c <= '7') { i *= 8; i += c - '0'; } else { (*string_ptr)--; break; } } return i; } default: return c; }}/* Print the character C on STREAM as part of the contents of a literal string whose delimiter is QUOTER. */voidprintchar (c, stream, quoter) register int c; FILE *stream; int quoter;{ c &= 0xFF; /* Avoid sign bit follies */ if ( c < 0x20 || /* Low control chars */ (c >= 0x7F && c < 0xA0) || /* DEL, High controls */ (sevenbit_strings && c >= 0x80)) { /* high order bit set */ switch (c) { case '\n': fputs_filtered ("\\n", stream); break; case '\b': fputs_filtered ("\\b", stream); break; case '\t': fputs_filtered ("\\t", stream); break; case '\f': fputs_filtered ("\\f", stream); break; case '\r': fputs_filtered ("\\r", stream); break; case '\033': fputs_filtered ("\\e", stream); break; case '\007': fputs_filtered ("\\a", stream); break; default: fprintf_filtered (stream, "\\%X", (unsigned int) c); break; } } else { if (c == '\\' || c == quoter) fputs_filtered ("\\", stream); fprintf_filtered (stream, "%c", c); }}/* Number of lines per page or UINT_MAX if paging is disabled. */static unsigned int lines_per_page;/* Number of chars per line or UNIT_MAX is line folding is disabled. */static unsigned int chars_per_line;/* Current count of lines printed on this page, chars on this line. */static unsigned int lines_printed, chars_printed;/* Buffer and start column of buffered text, for doing smarter word- wrapping. When someone calls wrap_here(), we start buffering output that comes through fputs_filtered(). If we see a newline, we just spit it out and forget about the wrap_here(). If we see another wrap_here(), we spit it out and remember the newer one. If we see the end of the line, we spit out a newline, the indent, and then the buffered output. wrap_column is the column number on the screen where wrap_buffer begins. When wrap_column is zero, wrapping is not in effect. wrap_buffer is malloc'd with chars_per_line+2 bytes. When wrap_buffer[0] is null, the buffer is empty. wrap_pointer points into it at the next character to fill. wrap_indent is the string that should be used as indentation if the wrap occurs. */static char *wrap_buffer, *wrap_pointer, *wrap_indent;static int wrap_column;/* ARGSUSED */static void set_width_command (args, from_tty, c) char *args; int from_tty; struct cmd_list_element *c;{ if (!wrap_buffer) { wrap_buffer = (char *) xmalloc (chars_per_line + 2); wrap_buffer[0] = '\0'; } else wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2); wrap_pointer = wrap_buffer; /* Start it at the beginning */}extern FILE *instream;static voidinstream_cleanup(stream) FILE *stream;{ instream = stream;}static voidprompt_for_continue (){ if (ISATTY(stdin) && ISATTY(stdout)) { struct cleanup *old_chain = make_cleanup(instream_cleanup, instream); char *cp; instream = stdin; immediate_quit++; cp = gdb_readline ("---Type <return> to continue---"); if (cp) free (cp); chars_printed = lines_printed = 0; immediate_quit--; do_cleanups(old_chain); dont_repeat (); /* Forget prev cmd -- CR won't repeat it. */ }}/* Reinitialize filter; ie. tell it to reset to original values. */voidreinitialize_more_filter (){ lines_printed = 0; chars_printed = 0;}/* Indicate that if the next sequence of characters overflows the line, a newline should be inserted here rather than when it hits the end. If INDENT is nonzero, it is a string to be printed to indent the wrapped part on the next line. INDENT must remain accessible until the next call to wrap_here() or until a newline is printed through fputs_filtered(). If the line is already overfull, we immediately print a newline and the indentation, and disable further wrapping. If we don't know the width of lines, but we know the page height, we must not wrap words, but should still keep track of newlines that were explicitly printed. INDENT should not contain tabs, as that will mess up the char count on the next line. FIXME. */voidwrap_here(indent) char *indent;{ if (wrap_buffer[0]) { *wrap_pointer = '\0'; fputs (wrap_buffer, stdout); } wrap_pointer = wrap_buffer; wrap_buffer[0] = '\0'; if (chars_per_line == UINT_MAX) /* No line overflow checking */ { wrap_column = 0; } else if (chars_printed >= chars_per_line) { puts_filtered ("\n"); puts_filtered (indent); wrap_column = 0; } else { wrap_column = chars_printed; wrap_indent = indent; }}/* Like fputs but pause after every screenful, and can wrap at points other than the final character of a line. Unlike fputs, fputs_filtered does not return a value. It is OK for LINEBUFFER to be NULL, in which case just don't print anything. Note 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. */voidfputs_filtered (linebuffer, stream) const char *linebuffer; FILE *stream;{ const char *lineptr; if (linebuffer == 0) return; /* Don't do any filtering if it is disabled. */ if (stream != stdout || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX)) { fputs (linebuffer, stream); return; } /* Go through and output each character. Show line extension when this is necessary; prompt user for new page when this is necessary. */ lineptr = linebuffer; while (*lineptr) { /* Possible new page. */ if (lines_printed >= lines_per_page - 1) prompt_for_continue (); while (*lineptr && *lineptr != '\n') { /* Print a single line. */ if (*lineptr == '\t') { if (wrap_column) *wrap_pointer++ = '\t'; else putc ('\t', stream); /* Shifting right by 3 produces the number of tab stops we have already passed, and then adding one and shifting left 3 advances to the next tab stop. */ chars_printed = ((chars_printed >> 3) + 1) << 3; lineptr++; } else { if (wrap_column) *wrap_pointer++ = *lineptr; else putc (*lineptr, stream); chars_printed++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -