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