0.7.4.19:
[sbcl.git] / src / runtime / interr.c
1 /*
2  * stuff to handle internal errors
3  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15
16 #include <stdio.h>
17 #include <stdarg.h>
18 #include <stdlib.h>
19
20 #include "arch.h"
21 #include "signal.h"
22
23 #include "runtime.h"
24 #include "sbcl.h"
25 #include "interr.h"
26 #include "print.h"
27 #include "lispregs.h"
28 \f
29 /* the way that we shut down the system on a fatal error */
30
31 static void
32 default_lossage_handler(void)
33 {
34     exit(1);
35 }
36 static void (*lossage_handler)(void) = default_lossage_handler;
37 void
38 set_lossage_handler(void handler(void))
39 {
40     lossage_handler = handler;
41 }
42
43 never_returns
44 lose(char *fmt, ...)
45 {
46     va_list ap;
47     fprintf(stderr, "fatal error encountered in SBCL runtime system");
48     if (fmt) {
49         fprintf(stderr, ":\n");
50         va_start(ap, fmt);
51         vfprintf(stderr, fmt, ap);
52         va_end(ap);
53     }
54     fprintf(stderr, "\n");
55     fflush(stderr);
56     lossage_handler();
57     fprintf(stderr, "Argh! lossage_handler() returned, total confusion..\n");
58     exit(1);
59 }
60 \f
61 /* internal error handler for when the Lisp error system doesn't exist
62  *
63  * FIXME: Shouldn't error output go to stderr instead of stdout? (Alas,
64  * this'd require changes in a number of things like brief_print(..),
65  * or I'd have changed it immediately.) */
66 void
67 describe_internal_error(os_context_t *context)
68 {
69     unsigned char *ptr = arch_internal_error_arguments(context);
70     int len, scoffset, sc, offset, ch;
71
72     len = *ptr++;
73     printf("internal error #%d\n", *ptr++);
74     len--;
75     while (len > 0) {
76         scoffset = *ptr++;
77         len--;
78         if (scoffset == 253) {
79             scoffset = *ptr++;
80             len--;
81         }
82         else if (scoffset == 254) {
83             scoffset = ptr[0] + ptr[1]*256;
84             ptr += 2;
85             len -= 2;
86         }
87         else if (scoffset == 255) {
88             scoffset = ptr[0] + (ptr[1]<<8) + (ptr[2]<<16) + (ptr[3]<<24);
89             ptr += 4;
90             len -= 4;
91         }
92         sc = scoffset & 0x1f;
93         offset = scoffset >> 5;
94                 
95         printf("    SC: %d, Offset: %d", sc, offset);
96         switch (sc) {
97         case sc_AnyReg:
98         case sc_DescriptorReg:
99             putchar('\t');
100             brief_print(*os_context_register_addr(context, offset));
101             break;
102
103         case sc_BaseCharReg:
104             ch = *os_context_register_addr(context, offset);
105 #ifdef __i386__
106             if (offset&1)
107                 ch = ch>>8;
108             ch = ch & 0xff;
109 #endif
110             switch (ch) {
111             case '\n': printf("\t'\\n'\n"); break;
112             case '\b': printf("\t'\\b'\n"); break;
113             case '\t': printf("\t'\\t'\n"); break;
114             case '\r': printf("\t'\\r'\n"); break;
115             default:
116                 if (ch < 32 || ch > 127)
117                     printf("\\%03o", ch);
118                 else
119                     printf("\t'%c'\n", ch);
120                 break;
121             }
122             break;
123         case sc_SapReg:
124 #ifdef sc_WordPointerReg
125         case sc_WordPointerReg:
126 #endif
127             printf("\t0x%08x\n", *os_context_register_addr(context, offset));
128             break;
129         case sc_SignedReg:
130             printf("\t%d\n", *os_context_register_addr(context, offset));
131             break;
132         case sc_UnsignedReg:
133             printf("\t%u\n", *os_context_register_addr(context, offset));
134             break;
135 #ifdef sc_SingleFloatReg
136         case sc_SingleFloatReg:
137             printf("\t%g\n", *(float *)&context->sc_fpregs[offset]);
138             break;
139 #endif
140 #ifdef sc_DoubleFloatReg
141         case sc_DoubleFloatReg:
142             printf("\t%g\n", *(double *)&context->sc_fpregs[offset]);
143             break;
144 #endif
145         default:
146             printf("\t???\n");
147             break;
148         }
149     }
150 }
151 \f
152 /* utility routines used by miscellaneous pieces of code */
153
154 lispobj debug_print(lispobj string)
155 {
156     /* This is a kludge.  It's not actually safe - in general - to use 
157        %primitive print on the alpha, because it skips half of the
158        number stack setup that should usually be done on a function call,
159        so the called routine (i.e. this one) ends up being able to overwrite
160        local variables in the caller.  Rather than fix this everywhere
161        that %primitive print is used (it's only a debugging aid anyway)
162        we just put guarantee our safety by putting an unused buffer on
163        the stack before doing anything else here */
164     char untouched[32]; /* GCC warns about not using this, but that's the point.. */
165     fprintf(stderr, "%s\n", 
166             (char *)(((struct vector *)native_pointer(string))->data),untouched);
167     return NIL;
168 }