|
|
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.