Clean up RCS ids
[projects/cmucl/cmucl.git] / src / lisp / interr.c
CommitLineData
62957726 1/*
62957726 2 * Stuff to handle internal errors.
3 *
4 */
5
6#include <stdio.h>
7#include <stdarg.h>
3cefc21b 8#include <stdlib.h>
62957726 9
3861a7bf 10#include "arch.h"
62957726 11#include "signal.h"
12
13#include "lisp.h"
14#include "internals.h"
15#include "interr.h"
16#include "print.h"
17#include "lispregs.h"
62957726 18\f
9a8c1c2f 19
62957726 20/* Lossage handler. */
21
9a8c1c2f 22static void
23default_lossage_handler(void)
62957726 24{
25 exit(1);
26}
27
9a8c1c2f 28static void (*lossage_handler) (void) = default_lossage_handler;
62957726 29
9a8c1c2f 30void
31set_lossage_handler(void handler(void))
62957726 32{
33 lossage_handler = handler;
34}
35
9a8c1c2f 36void
37lose(char *fmt, ...)
62957726 38{
39 va_list ap;
40
41 if (fmt != NULL) {
42 va_start(ap, fmt);
43 vfprintf(stderr, fmt, ap);
44 fflush(stderr);
45 va_end(ap);
46 }
47 lossage_handler();
48}
62957726 49\f
9a8c1c2f 50
62957726 51/* Internal error handler for when the Lisp error system doesn't exist. */
52
53static char *errors[] = ERRORS;
54
9a8c1c2f 55void
56internal_error(os_context_t * context)
62957726 57{
58 unsigned char *ptr = arch_internal_error_arguments(context);
59 int len, scoffset, sc, offset, ch;
60
61 len = *ptr++;
62 printf("Error: %s\n", errors[*ptr++]);
63 len--;
64 while (len > 0) {
65 scoffset = *ptr++;
66 len--;
67 if (scoffset == 253) {
68 scoffset = *ptr++;
69 len--;
9a8c1c2f 70 } else if (scoffset == 254) {
71 scoffset = ptr[0] + ptr[1] * 256;
62957726 72 ptr += 2;
73 len -= 2;
9a8c1c2f 74 } else if (scoffset == 255) {
75 scoffset = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
62957726 76 ptr += 4;
77 len -= 4;
78 }
79 sc = scoffset & 0x1f;
80 offset = scoffset >> 5;
9a8c1c2f 81
62957726 82 printf(" SC: %d, Offset: %d", sc, offset);
83 switch (sc) {
84 case sc_AnyReg:
85 case sc_DescriptorReg:
9a8c1c2f 86 putchar('\t');
87 brief_print(SC_REG(context, offset));
88 break;
62957726 89
90 case sc_BaseCharReg:
9a8c1c2f 91 ch = SC_REG(context, offset);
62957726 92#ifdef i386
9a8c1c2f 93 if (offset & 1)
94 ch = ch >> 8;
95 ch = ch & 0xff;
62957726 96#endif
9a8c1c2f 97 switch (ch) {
98 case '\n':
99 printf("\t'\\n'\n");
100 break;
101 case '\b':
102 printf("\t'\\b'\n");
103 break;
104 case '\t':
105 printf("\t'\\t'\n");
106 break;
107 case '\r':
108 printf("\t'\\r'\n");
109 break;
110 default:
111 if (ch < 32 || ch > 127)
112 printf("\\%03o", ch);
113 else
114 printf("\t'%c'\n", ch);
115 break;
116 }
117 break;
62957726 118 case sc_SapReg:
119#ifdef sc_WordPointerReg
120 case sc_WordPointerReg:
121#endif
44e0351e 122 printf("\t0x%08lx\n", SC_REG(context, offset));
9a8c1c2f 123 break;
62957726 124 case sc_SignedReg:
44e0351e 125 printf("\t%ld\n", SC_REG(context, offset));
9a8c1c2f 126 break;
62957726 127 case sc_UnsignedReg:
44e0351e 128 printf("\t%lu\n", SC_REG(context, offset));
9a8c1c2f 129 break;
130#if 0 /* broken */
9aa51d29 131#ifdef sc_SingleReg
132 case sc_SingleReg:
9a8c1c2f 133 printf("\t%g\n", *(float *) &context->sc_fpregs[offset]);
134 break;
62957726 135#endif
9aa51d29 136#ifdef sc_DoubleReg
137 case sc_DoubleReg:
9a8c1c2f 138 printf("\t%g\n", *(double *) &context->sc_fpregs[offset]);
139 break;
62957726 140#endif
9aa51d29 141#ifdef sc_LongReg
142 case sc_LongReg:
9a8c1c2f 143 printf("\t%Lg\n", *(long double *) &context->sc_fpregs[offset]);
144 break;
9aa51d29 145#endif
146#endif
62957726 147 default:
9a8c1c2f 148 printf("\t???\n");
149 break;
62957726 150 }
151 }
152
153 lose(NULL);
154}
9a8c1c2f 155\f
62957726 156
157
158
62957726 159/* Utility routines used by random pieces of code. */
160
88d77e83 161#if defined(UNICODE)
0dae4884
RT
162
163/* The Unicode replacement character code */
164#define REPLACEMENT_CODE 0xfffd
165
88d77e83
RT
166/*
167 * Convert a unicode code point to a set of utf8-encoded octets to
168 * standard output. This is the algorithm used by the Lisp utf8
169 * encoder in src/code/extfmts.lisp.
170 */
171static void
172utf8(int code, int len)
173{
174 int k;
175 int j = 6 - len;
176 int p = 6 * len;
177 int init = 0xff & (0x7e << j);
178 int c;
179
180 /*
181 * (ldb (byte j p) code): Extract j bits from position p of the code
182 */
183 c = (code >> p) & ((1 << j) - 1);
184
185 putchar(init | c);
186
187 for (k = 0; k < len; ++k) {
188 p -= 6;
189 /* (ldb (byte 6 p) code) */
190 c = (code >> p) & ((1 << 6) - 1);
191 putchar(128 | c);
192 }
193}
194
195/*
196 * Test if code is a surrogate. Returns true if so. If the code is a
197 * surrogate, then type indicates if it is a high (0) or low (1)
198 * surrogate. If not a surrogate, type is not modified. If type is
199 * NULL, then no type is returned.
200 */
0dae4884 201static boolean
88d77e83
RT
202surrogatep(int code, int *type)
203{
204 boolean result;
205
206 if ((code >> 11) == 0x1b) {
207 result = 1;
208 if (type) {
209 *type = (code >> 10) & 1;
210 }
211 } else {
212 result = 0;
213 }
214
215 return result;
216}
217
218/*
219 * Convert one or two utf16 code units into a code point. utf16
220 * points to the string, len is the length of the string. The
221 * codepoint is returned and the number of code units consumed is
222 * returned in consumed.
223 */
0dae4884 224static int
88d77e83
RT
225utf16_codepoint(unsigned short int* utf16, int len, int* consumed)
226{
ff569406
RT
227 int codepoint = REPLACEMENT_CODE;
228 int code_unit = *utf16;
88d77e83 229 int code_type;
ff569406 230 int read = 1;
88d77e83
RT
231
232 /*
233 * If the current code unit is not a surrogate, we're done.
ff569406
RT
234 * Otherwise process the surrogate. If this is a high (leading)
235 * surrogate and the next code unit is a low (trailing) surrogate,
236 * compute the code point. Otherwise we have a bare surrogate or
237 * an invalid surrogate sequence, so just return the replacement
238 * character.
88d77e83
RT
239 */
240
ff569406
RT
241 if (surrogatep(code_unit, &code_type)) {
242 if (code_type == 0 && len > 0) {
243 int next_unit = utf16[1];
88d77e83 244 int next_type;
ff569406
RT
245 if (surrogatep(next_unit, &next_type)) {
246 if (next_type == 1) {
88d77e83 247 /* High followed by low surrogate */
ff569406 248 codepoint = ((code_unit - 0xd800) << 10) + next_unit + 0x2400;
88d77e83 249 ++read;
88d77e83 250 }
88d77e83 251 }
88d77e83 252 }
ff569406
RT
253 } else {
254 codepoint = code_unit;
88d77e83
RT
255 }
256
257 *consumed = read;
ff569406 258 return codepoint;
88d77e83
RT
259}
260
261/*
262 * Send the utf-16 Lisp unicode string to standard output as a
263 * utf8-encoded sequence of octets.
264 */
265static void
266utf16_output(unsigned short int* utf16, int len)
267{
268 while (len) {
269 int consumed;
270 int code = utf16_codepoint(utf16, len, &consumed);
271
272 /* Output the codepoint */
273 if (code < 0x80) {
274 putchar(code);
275 } else if (code < 0x800) {
276 utf8(code, 1);
277 } else if (code < 0x10000) {
278 utf8(code, 2);
279 } else if (code < 0x110000) {
280 utf8(code, 3);
281 } else {
282 /*
283 * This shouldn't happen, but if it does we don't want to
284 * signal any kind of error so just output a question mark
285 * so we can continue.
286 */
287 putchar('?');
288 }
289
290 len -= consumed;
291 utf16 += consumed;
292 }
293}
294#endif
295
296/*
297 * debug_print is used by %primitive print to output a string.
298 */
9a8c1c2f 299lispobj
68ac9a3e 300debug_print(lispobj object)
62957726 301{
68ac9a3e 302
303#ifndef UNICODE
304 printf("%s\n", (char *) (((struct vector *) PTR(object))->data));
f7f9348b 305 fflush(stdout);
68ac9a3e 306#else
307 if (Pointerp(object)) {
308 struct vector *lisp_string = (struct vector*) PTR(object);
309
310 if ((unsigned long) lisp_string->header == type_SimpleString) {
311 unsigned short int* lisp_chars;
312 int len;
68ac9a3e 313
314 len = lisp_string->length >> 2;
315 lisp_chars = (unsigned short int*) lisp_string->data;
2997c7c8 316
88d77e83 317 utf16_output(lisp_chars, len);
68ac9a3e 318 putchar('\n');
319
320 fflush(stdout);
321 } else {
322 print(object);
323 }
324 } else {
88d77e83 325 /*
ff569406
RT
326 * We shouldn't actually ever get here because %primitive
327 * print is only supposed to take strings. But if we do, it's
88d77e83
RT
328 * useful to print something out anyway.
329 */
68ac9a3e 330#if 1
331 printf("obj @0x%lx: ", (unsigned long) object);
332#endif
333 print(object);
334 }
335#endif
62957726 336 return NIL;
337}
68ac9a3e 338