|
|
1.1 ! root 1: /* General utility routines for GDB, the GNU debugger. ! 2: Copyright (C) 1986 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 <signal.h> ! 23: #include <sys/ioctl.h> ! 24: #include "defs.h" ! 25: #include "param.h" ! 26: #ifdef HAVE_TERMIO ! 27: #include <termio.h> ! 28: #endif ! 29: ! 30: void error (); ! 31: void fatal (); ! 32: ! 33: /* Chain of cleanup actions established with make_cleanup, ! 34: to be executed if an error happens. */ ! 35: ! 36: static struct cleanup *cleanup_chain; ! 37: ! 38: /* Nonzero means a quit has been requested. */ ! 39: ! 40: int quit_flag; ! 41: ! 42: /* Nonzero means quit immediately if Control-C is typed now, ! 43: rather than waiting until QUIT is executed. */ ! 44: ! 45: int immediate_quit; ! 46: ! 47: /* Add a new cleanup to the cleanup_chain, ! 48: and return the previous chain pointer ! 49: to be passed later to do_cleanups or discard_cleanups. ! 50: Args are FUNCTION to clean up with, and ARG to pass to it. */ ! 51: ! 52: struct cleanup * ! 53: make_cleanup (function, arg) ! 54: void (*function) (); ! 55: int arg; ! 56: { ! 57: register struct cleanup *new ! 58: = (struct cleanup *) xmalloc (sizeof (struct cleanup)); ! 59: register struct cleanup *old_chain = cleanup_chain; ! 60: ! 61: new->next = cleanup_chain; ! 62: new->function = function; ! 63: new->arg = arg; ! 64: cleanup_chain = new; ! 65: ! 66: return old_chain; ! 67: } ! 68: ! 69: /* Discard cleanups and do the actions they describe ! 70: until we get back to the point OLD_CHAIN in the cleanup_chain. */ ! 71: ! 72: void ! 73: do_cleanups (old_chain) ! 74: register struct cleanup *old_chain; ! 75: { ! 76: register struct cleanup *ptr; ! 77: while ((ptr = cleanup_chain) != old_chain) ! 78: { ! 79: (*ptr->function) (ptr->arg); ! 80: cleanup_chain = ptr->next; ! 81: free (ptr); ! 82: } ! 83: } ! 84: ! 85: /* Discard cleanups, not doing the actions they describe, ! 86: until we get back to the point OLD_CHAIN in the cleanup_chain. */ ! 87: ! 88: void ! 89: discard_cleanups (old_chain) ! 90: register struct cleanup *old_chain; ! 91: { ! 92: register struct cleanup *ptr; ! 93: while ((ptr = cleanup_chain) != old_chain) ! 94: { ! 95: cleanup_chain = ptr->next; ! 96: free (ptr); ! 97: } ! 98: } ! 99: ! 100: /* This function is useful for cleanups. ! 101: Do ! 102: ! 103: foo = xmalloc (...); ! 104: old_chain = make_cleanup (free_current_contents, &foo); ! 105: ! 106: to arrange to free the object thus allocated. */ ! 107: ! 108: void ! 109: free_current_contents (location) ! 110: char **location; ! 111: { ! 112: free (*location); ! 113: } ! 114: ! 115: /* Generally useful subroutines used throughout the program. */ ! 116: ! 117: /* Like malloc but get error if no storage available. */ ! 118: ! 119: char * ! 120: xmalloc (size) ! 121: long size; ! 122: { ! 123: register char *val = (char *) malloc (size); ! 124: if (!val) ! 125: fatal ("virtual memory exhausted.", 0); ! 126: return val; ! 127: } ! 128: ! 129: /* Like realloc but get error if no storage available. */ ! 130: ! 131: char * ! 132: xrealloc (ptr, size) ! 133: char *ptr; ! 134: long size; ! 135: { ! 136: register char *val = (char *) realloc (ptr, size); ! 137: if (!val) ! 138: fatal ("virtual memory exhausted.", 0); ! 139: return val; ! 140: } ! 141: ! 142: /* Print the system error message for errno, and also mention STRING ! 143: as the file name for which the error was encountered. ! 144: Then return to command level. */ ! 145: ! 146: void ! 147: perror_with_name (string) ! 148: char *string; ! 149: { ! 150: extern int sys_nerr; ! 151: extern char *sys_errlist[]; ! 152: extern int errno; ! 153: char *err; ! 154: char *combined; ! 155: ! 156: if (errno < sys_nerr) ! 157: err = sys_errlist[errno]; ! 158: else ! 159: err = "unknown error"; ! 160: ! 161: combined = (char *) alloca (strlen (err) + strlen (string) + 3); ! 162: strcpy (combined, string); ! 163: strcat (combined, ": "); ! 164: strcat (combined, err); ! 165: ! 166: error ("%s.", combined); ! 167: } ! 168: ! 169: /* Print the system error message for ERRCODE, and also mention STRING ! 170: as the file name for which the error was encountered. */ ! 171: ! 172: void ! 173: print_sys_errmsg (string, errcode) ! 174: char *string; ! 175: int errcode; ! 176: { ! 177: extern int sys_nerr; ! 178: extern char *sys_errlist[]; ! 179: char *err; ! 180: char *combined; ! 181: ! 182: if (errcode < sys_nerr) ! 183: err = sys_errlist[errcode]; ! 184: else ! 185: err = "unknown error"; ! 186: ! 187: combined = (char *) alloca (strlen (err) + strlen (string) + 3); ! 188: strcpy (combined, string); ! 189: strcat (combined, ": "); ! 190: strcat (combined, err); ! 191: ! 192: printf ("%s.\n", combined); ! 193: } ! 194: ! 195: void ! 196: quit () ! 197: { ! 198: fflush (stdout); ! 199: #ifdef HAVE_TERMIO ! 200: ioctl (fileno (stdout), TCFLSH, 1); ! 201: #else /* not HAVE_TERMIO */ ! 202: ioctl (fileno (stdout), TIOCFLUSH, 0); ! 203: #endif /* not HAVE_TERMIO */ ! 204: #ifdef TIOCGPGRP ! 205: error ("Quit"); ! 206: #else ! 207: error ("Quit (expect signal %d when inferior is resumed)", SIGINT); ! 208: #endif /* TIOCGPGRP */ ! 209: } ! 210: ! 211: /* Control C comes here */ ! 212: ! 213: void ! 214: request_quit () ! 215: { ! 216: quit_flag = 1; ! 217: if (immediate_quit) ! 218: quit (); ! 219: } ! 220: ! 221: /* Print an error message and return to command level. ! 222: STRING is the error message, used as a fprintf string, ! 223: and ARG is passed as an argument to it. */ ! 224: ! 225: void ! 226: error (string, arg1, arg2, arg3) ! 227: char *string; ! 228: int arg1, arg2, arg3; ! 229: { ! 230: fflush (stdout); ! 231: fprintf (stderr, string, arg1, arg2, arg3); ! 232: fprintf (stderr, "\n"); ! 233: return_to_top_level (); ! 234: } ! 235: ! 236: /* Print an error message and exit reporting failure. ! 237: This is for a error that we cannot continue from. ! 238: STRING and ARG are passed to fprintf. */ ! 239: ! 240: void ! 241: fatal (string, arg) ! 242: char *string; ! 243: int arg; ! 244: { ! 245: fprintf (stderr, "gdb: "); ! 246: fprintf (stderr, string, arg); ! 247: fprintf (stderr, "\n"); ! 248: exit (1); ! 249: } ! 250: ! 251: /* Make a copy of the string at PTR with SIZE characters ! 252: (and add a null character at the end in the copy). ! 253: Uses malloc to get the space. Returns the address of the copy. */ ! 254: ! 255: char * ! 256: savestring (ptr, size) ! 257: char *ptr; ! 258: int size; ! 259: { ! 260: register char *p = (char *) xmalloc (size + 1); ! 261: bcopy (ptr, p, size); ! 262: p[size] = 0; ! 263: return p; ! 264: } ! 265: ! 266: char * ! 267: concat (s1, s2, s3) ! 268: char *s1, *s2, *s3; ! 269: { ! 270: register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1; ! 271: register char *val = (char *) xmalloc (len); ! 272: strcpy (val, s1); ! 273: strcat (val, s2); ! 274: strcat (val, s3); ! 275: return val; ! 276: } ! 277: ! 278: void ! 279: print_spaces (n, file) ! 280: register int n; ! 281: register FILE *file; ! 282: { ! 283: while (n-- > 0) ! 284: fputc (' ', file); ! 285: } ! 286: ! 287: /* Ask user a y-or-n question and return 1 iff answer is yes. ! 288: Takes three args which are given to printf to print the question. ! 289: The first, a control string, should end in "? ". ! 290: It should not say how to answer, because we do that. */ ! 291: ! 292: int ! 293: query (ctlstr, arg1, arg2) ! 294: char *ctlstr; ! 295: { ! 296: register int answer; ! 297: ! 298: /* Automatically answer "yes" if input is not from a terminal. */ ! 299: if (!input_from_terminal_p ()) ! 300: return 1; ! 301: ! 302: while (1) ! 303: { ! 304: printf (ctlstr, arg1, arg2); ! 305: printf ("(y or n) "); ! 306: fflush (stdout); ! 307: answer = fgetc (stdin); ! 308: clearerr (stdin); /* in case of C-d */ ! 309: if (answer != '\n') ! 310: while (fgetc (stdin) != '\n') clearerr (stdin); ! 311: if (answer >= 'a') ! 312: answer -= 040; ! 313: if (answer == 'Y') ! 314: return 1; ! 315: if (answer == 'N') ! 316: return 0; ! 317: printf ("Please answer y or n.\n"); ! 318: } ! 319: } ! 320: ! 321: /* Parse a C escape sequence. STRING_PTR points to a variable ! 322: containing a pointer to the string to parse. That pointer ! 323: is updated past the characters we use. The value of the ! 324: escape sequence is returned. ! 325: ! 326: A negative value means the sequence \ newline was seen, ! 327: which is supposed to be equivalent to nothing at all. ! 328: ! 329: If \ is followed by a null character, we return a negative ! 330: value and leave the string pointer pointing at the null character. ! 331: ! 332: If \ is followed by 000, we return 0 and leave the string pointer ! 333: after the zeros. A value of 0 does not mean end of string. */ ! 334: ! 335: int ! 336: parse_escape (string_ptr) ! 337: char **string_ptr; ! 338: { ! 339: register int c = *(*string_ptr)++; ! 340: switch (c) ! 341: { ! 342: case 'a': ! 343: return '\a'; ! 344: case 'b': ! 345: return '\b'; ! 346: case 'e': ! 347: return 033; ! 348: case 'f': ! 349: return '\f'; ! 350: case 'n': ! 351: return '\n'; ! 352: case 'r': ! 353: return '\r'; ! 354: case 't': ! 355: return '\t'; ! 356: case 'v': ! 357: return '\v'; ! 358: case '\n': ! 359: return -2; ! 360: case 0: ! 361: (*string_ptr)--; ! 362: return 0; ! 363: case '^': ! 364: c = *(*string_ptr)++; ! 365: if (c == '\\') ! 366: c = parse_escape (string_ptr); ! 367: if (c == '?') ! 368: return 0177; ! 369: return (c & 0200) | (c & 037); ! 370: ! 371: case '0': ! 372: case '1': ! 373: case '2': ! 374: case '3': ! 375: case '4': ! 376: case '5': ! 377: case '6': ! 378: case '7': ! 379: { ! 380: register int i = c - '0'; ! 381: register int count = 0; ! 382: while (++count < 3) ! 383: { ! 384: if ((c = *(*string_ptr)++) >= '0' && c <= '7') ! 385: { ! 386: i *= 8; ! 387: i += c - '0'; ! 388: } ! 389: else ! 390: { ! 391: (*string_ptr)--; ! 392: break; ! 393: } ! 394: } ! 395: return i; ! 396: } ! 397: default: ! 398: return c; ! 399: } ! 400: } ! 401: ! 402: /* Print the character CH on STREAM as part of the contents ! 403: of a literal string whose delimiter is QUOTER. */ ! 404: ! 405: void ! 406: printchar (ch, stream, quoter) ! 407: unsigned char ch; ! 408: FILE *stream; ! 409: int quoter; ! 410: { ! 411: register int c = ch; ! 412: if (c < 040 || c >= 0177) ! 413: { ! 414: if (c == '\n') ! 415: fprintf (stream, "\\n"); ! 416: else if (c == '\b') ! 417: fprintf (stream, "\\b"); ! 418: else if (c == '\t') ! 419: fprintf (stream, "\\t"); ! 420: else if (c == '\f') ! 421: fprintf (stream, "\\f"); ! 422: else if (c == '\r') ! 423: fprintf (stream, "\\r"); ! 424: else if (c == 033) ! 425: fprintf (stream, "\\e"); ! 426: else if (c == '\a') ! 427: fprintf (stream, "\\a"); ! 428: else ! 429: fprintf (stream, "\\%03o", c); ! 430: } ! 431: else ! 432: { ! 433: if (c == '\\' || c == quoter) ! 434: fputc ('\\', stream); ! 435: fputc (c, stream); ! 436: } ! 437: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.