Changed throw_cacao_exception_exit to support variable arguments (...).
[cacao.git] / src / vm / exceptions.c
1 /* exceptions.c - exception related functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    $Id: exceptions.c 1435 2004-11-05 09:48:33Z twisti $
30
31 */
32
33
34 #include <string.h>
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include "asmpart.h"
38 #include "global.h"
39 #include "loader.h"
40 #include "native.h"
41 #include "tables.h"
42 #include "jit/jit.h"
43 #include "toolbox/logging.h"
44 #include "toolbox/memory.h"
45 #include "nat/java_lang_String.h"
46 #include "nat/java_lang_Throwable.h"
47
48
49 /* system exception classes required in cacao */
50
51 classinfo *class_java_lang_Throwable;
52 classinfo *class_java_lang_Exception;
53 classinfo *class_java_lang_Error;
54 classinfo *class_java_lang_OutOfMemoryError;
55
56
57 /* exception/error super class */
58
59 char *string_java_lang_Throwable =
60     "java/lang/Throwable";
61
62 char *string_java_lang_VMThrowable =
63     "java/lang/VMThrowable";
64
65
66 /* specify some exception strings for code generation */
67
68 char *string_java_lang_ArithmeticException =
69     "java/lang/ArithmeticException";
70
71 char *string_java_lang_ArithmeticException_message =
72     "/ by zero";
73
74 char *string_java_lang_ArrayIndexOutOfBoundsException =
75     "java/lang/ArrayIndexOutOfBoundsException";
76
77 char *string_java_lang_ArrayStoreException =
78     "java/lang/ArrayStoreException";
79
80 char *string_java_lang_ClassCastException =
81     "java/lang/ClassCastException";
82
83 char *string_java_lang_ClassNotFoundException =
84         "java/lang/ClassNotFoundException";
85
86 char *string_java_lang_CloneNotSupportedException =
87     "java/lang/CloneNotSupportedException";
88
89 char *string_java_lang_Exception =
90     "java/lang/Exception";
91
92 char *string_java_lang_IllegalArgumentException =
93     "java/lang/IllegalArgumentException";
94
95 char *string_java_lang_IllegalMonitorStateException =
96     "java/lang/IllegalMonitorStateException";
97
98 char *string_java_lang_IndexOutOfBoundsException =
99     "java/lang/IndexOutOfBoundsException";
100
101 char *string_java_lang_InterruptedException =
102     "java/lang/InterruptedException";
103
104 char *string_java_lang_NegativeArraySizeException =
105     "java/lang/NegativeArraySizeException";
106
107 char *string_java_lang_NoSuchFieldException =
108         "java/lang/NoSuchFieldException";
109
110 char *string_java_lang_NoSuchMethodException =
111         "java/lang/NoSuchMethodException";
112
113 char *string_java_lang_NullPointerException =
114     "java/lang/NullPointerException";
115
116
117 /* specify some error strings for code generation */
118
119 char *string_java_lang_AbstractMethodError =
120     "java/lang/AbstractMethodError";
121
122 char *string_java_lang_ClassCircularityError =
123     "java/lang/ClassCircularityError";
124
125 char *string_java_lang_ClassFormatError =
126     "java/lang/ClassFormatError";
127
128 char *string_java_lang_Error =
129     "java/lang/Error";
130
131 char *string_java_lang_ExceptionInInitializerError =
132     "java/lang/ExceptionInInitializerError";
133
134 char *string_java_lang_IncompatibleClassChangeError =
135     "java/lang/IncompatibleClassChangeError";
136
137 char *string_java_lang_InternalError =
138     "java/lang/InternalError";
139
140 char *string_java_lang_LinkageError =
141     "java/lang/LinkageError";
142
143 char *string_java_lang_NoClassDefFoundError =
144     "java/lang/NoClassDefFoundError";
145
146 char *string_java_lang_NoSuchFieldError =
147         "java/lang/NoSuchFieldError";
148
149 char *string_java_lang_NoSuchMethodError =
150         "java/lang/NoSuchMethodError";
151
152 char *string_java_lang_OutOfMemoryError =
153     "java/lang/OutOfMemoryError";
154
155 char *string_java_lang_UnsupportedClassVersionError =
156     "java/lang/UnsupportedClassVersionError";
157
158 char *string_java_lang_VerifyError =
159     "java/lang/VerifyError";
160
161 char *string_java_lang_VirtualMachineError =
162     "java/lang/VirtualMachineError";
163
164
165 /* init_system_exceptions *****************************************************
166
167    load, link and compile exceptions used in the system
168
169 *******************************************************************************/
170
171 void init_system_exceptions()
172 {
173         /* java/lang/Throwable */
174
175         class_java_lang_Throwable =
176                 class_new(utf_new_char(string_java_lang_Throwable));
177         class_load(class_java_lang_Throwable);
178         class_link(class_java_lang_Throwable);
179
180         /* java/lang/Exception */
181
182         class_java_lang_Exception =
183                 class_new(utf_new_char(string_java_lang_Exception));
184         class_load(class_java_lang_Exception);
185         class_link(class_java_lang_Exception);
186
187         /* java/lang/Error */
188
189         class_java_lang_Error =
190                 class_new(utf_new_char(string_java_lang_Error));
191         class_load(class_java_lang_Error);
192         class_link(class_java_lang_Error);
193
194         /* java/lang/OutOfMemoryError */
195
196         class_java_lang_OutOfMemoryError =
197                 class_new(utf_new_char(string_java_lang_OutOfMemoryError));
198         class_load(class_java_lang_OutOfMemoryError);
199         class_link(class_java_lang_OutOfMemoryError);
200 }
201
202
203 static void throw_exception_exit_intern(bool doexit)
204 {
205         java_objectheader *xptr;
206         classinfo *c;
207         methodinfo *pss;
208
209         if (*exceptionptr) {
210                 xptr = *exceptionptr;
211
212                 /* clear exception, because we are calling jit code again */
213                 *exceptionptr = NULL;
214
215                 c = xptr->vftbl->class;
216
217                 pss = class_resolveclassmethod(c,
218                                                                            utf_new_char("printStackTrace"),
219                                                                            utf_new_char("()V"),
220                                                                            class_java_lang_Object,
221                                                                            false);
222
223                 /* print the stacktrace */
224                 if (pss) {
225                         asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
226
227                         /* this normally means, we are EXTREMLY out of memory, but may be
228                            any other exception */
229                         if (*exceptionptr) {
230                                 utf_fprint_classname(stderr, c->name);
231                                 fprintf(stderr, "\n");
232                         }
233
234                 } else {
235                         utf_fprint_classname(stderr, c->name);
236                         fprintf(stderr, ": printStackTrace()V not found!\n");
237                 }
238
239                 fflush(stderr);
240
241                 /* good bye! */
242                 if (doexit) {
243                         exit(1);
244                 }
245         }
246 }
247
248
249 void throw_exception()
250 {
251         throw_exception_exit_intern(false);
252 }
253
254
255 void throw_exception_exit()
256 {
257         throw_exception_exit_intern(true);
258 }
259
260
261 void throw_main_exception()
262 {
263         fprintf(stderr, "Exception in thread \"main\" ");
264         fflush(stderr);
265
266         throw_exception_exit_intern(false);
267 }
268
269
270 void throw_main_exception_exit()
271 {
272         fprintf(stderr, "Exception in thread \"main\" ");
273         fflush(stderr);
274
275         throw_exception_exit_intern(true);
276 }
277
278
279 void throw_cacao_exception_exit(char *exception, char *message, ...)
280 {
281         s4 i;
282         char *tmp;
283         s4 len;
284         va_list ap;
285
286         len = strlen(exception);
287         tmp = MNEW(char, len+1);
288         strncpy(tmp, exception, len);
289         tmp[len]='\0';
290
291         /* convert to classname */
292
293         for (i = len - 1; i >= 0; i--) {
294                 if (tmp[i] == '/') tmp[i] = '.';
295         }
296
297         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
298
299         MFREE(tmp, char, len);
300
301         if (strlen(message) > 0) {
302                 fprintf(stderr, ": ");
303
304                 va_start(ap, message);
305                 fprintf(stderr, message, ap);
306                 va_end(ap);
307         }
308
309         fprintf(stderr, "\n");
310         fflush(stderr);
311
312         /* good bye! */
313         exit(1);
314 }
315
316
317 #if 1
318 #define CREATENEW_EXCEPTION(ex) \
319     return ex;
320 #else
321 #define CREATENEW_EXCEPTION(ex) \
322         java_objectheader *newEx; \
323         java_objectheader *oldexception=*exceptionptr;\
324         *exceptionptr=0;\
325         newEx=ex;\
326         *exceptionptr=oldexception;\
327         return newEx;
328 #endif
329
330 java_objectheader *new_exception(char *classname)
331 {
332         classinfo *c = class_new(utf_new_char(classname));
333
334         CREATENEW_EXCEPTION(native_new_and_init(c));
335 }
336
337 java_objectheader *new_exception_message(char *classname, char *message)
338 {
339         classinfo *c = class_new(utf_new_char(classname));
340
341         CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new_char(message)));
342 }
343
344
345 java_objectheader *new_exception_throwable(char *classname, java_lang_Throwable *throwable)
346 {
347         classinfo *c = class_new(utf_new_char(classname));
348
349         CREATENEW_EXCEPTION(native_new_and_init_throwable(c, throwable));
350 }
351
352
353 java_objectheader *new_exception_utfmessage(char *classname, utf *message)
354 {
355         classinfo *c = class_new(utf_new_char(classname));
356
357         CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new(message)));
358 }
359
360
361 java_objectheader *new_exception_javastring(char *classname, java_lang_String *message)
362 {
363         classinfo *c = class_new(utf_new_char(classname));
364
365         CREATENEW_EXCEPTION(native_new_and_init_string(c, message));
366 }
367
368
369 java_objectheader *new_exception_int(char *classname, s4 i)
370 {
371         classinfo *c;
372
373         c = class_new(utf_new_char(classname));
374
375         CREATENEW_EXCEPTION(native_new_and_init_int(c, i));
376 }
377
378
379 /* new_classformaterror ********************************************************
380
381    generates a java.lang.ClassFormatError for the classloader
382
383 *******************************************************************************/
384
385 java_objectheader *new_classformaterror(classinfo *c, char *message, ...)
386 {
387         char msg[MAXLOGTEXT];
388         va_list ap;
389
390         utf_sprint_classname(msg, c->name);
391         sprintf(msg + strlen(msg), " (");
392
393         va_start(ap, message);
394         vsprintf(msg + strlen(msg), message, ap);
395         va_end(ap);
396
397         sprintf(msg + strlen(msg), ")");
398
399         return new_exception_message(string_java_lang_ClassFormatError, msg);
400 }
401
402
403 /* new_unsupportedclassversionerror ********************************************
404
405    generates a java.lang.UnsupportedClassVersionError for the classloader
406
407 *******************************************************************************/
408
409 java_objectheader *new_unsupportedclassversionerror(classinfo *c, char *message, ...)
410 {
411         char msg[MAXLOGTEXT];
412         va_list ap;
413
414         utf_sprint_classname(msg, c->name);
415         sprintf(msg + strlen(msg), " (");
416
417         va_start(ap, message);
418         vsprintf(msg + strlen(msg), message, ap);
419         va_end(ap);
420
421         sprintf(msg + strlen(msg), ")");
422
423         return new_exception_message(string_java_lang_UnsupportedClassVersionError,
424                                                                  msg);
425 }
426
427
428 /* new_verifyerror *************************************************************
429
430    generates a java.lang.VerifyError for the jit compiler
431
432 *******************************************************************************/
433
434 java_objectheader *new_verifyerror(methodinfo *m, char *message)
435 {
436         java_objectheader *o;
437         char *msg;
438         s4 len;
439
440         len = 8 + utf_strlen(m->class->name) +
441                 10 + utf_strlen(m->name) +
442                 13 + utf_strlen(m->descriptor) +
443                 2 + strlen(message) + 1;
444                 
445         msg = MNEW(char, len);
446
447         sprintf(msg, "(class: ");
448         utf_sprint(msg + strlen(msg), m->class->name);
449         sprintf(msg + strlen(msg), ", method: ");
450         utf_sprint(msg + strlen(msg), m->name);
451         sprintf(msg + strlen(msg), ", signature: ");
452         utf_sprint(msg + strlen(msg), m->descriptor);
453         sprintf(msg + strlen(msg), ") %s", message);
454
455         o = new_exception_message(string_java_lang_VerifyError, msg);
456
457         MFREE(msg, u1, len);
458
459         return o;
460 }
461
462
463 /* new_arithmeticexception *****************************************************
464
465    generates a java.lang.ArithmeticException for the jit compiler
466
467 *******************************************************************************/
468
469 java_objectheader *new_arithmeticexception()
470 {
471         java_objectheader *e;
472
473         e = new_exception_message(string_java_lang_ArithmeticException,
474                                                           string_java_lang_ArithmeticException_message);
475
476         if (!e)
477                 return *exceptionptr;
478
479         return e;
480 }
481
482
483 /* new_arrayindexoutofboundsexception ******************************************
484
485    generates a java.lang.ArrayIndexOutOfBoundsException for the jit compiler
486
487 *******************************************************************************/
488
489 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
490 {
491         java_objectheader *e;
492         methodinfo *m;
493         java_lang_String *s;
494
495         /* convert the index into a String, like Sun does */
496
497         m = class_resolveclassmethod(class_java_lang_String,
498                                                                  utf_new_char("valueOf"),
499                                                                  utf_new_char("(I)Ljava/lang/String;"),
500                                                                  class_java_lang_Object,
501                                                                  true);
502
503         if (!m)
504                 return *exceptionptr;
505
506         s = (java_lang_String *) asm_calljavafunction(m,
507                                                                                                   (void *) index,
508                                                                                                   NULL,
509                                                                                                   NULL,
510                                                                                                   NULL);
511
512         if (!s)
513                 return *exceptionptr;
514
515         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
516                                                                  s);
517
518         if (!e)
519                 return *exceptionptr;
520
521         return e;
522 }
523
524
525 /* new_classcastexception ******************************************************
526
527    generates a java.lang.ClassCastException for the jit compiler
528
529 *******************************************************************************/
530
531 java_objectheader *new_classcastexception()
532 {
533         java_objectheader *e;
534
535         e = new_exception(string_java_lang_ClassCastException);
536
537         if (!e)
538                 return *exceptionptr;
539
540         return e;
541 }
542
543
544 /* new_negativearraysizeexception **********************************************
545
546    generates a java.lang.NegativeArraySizeException for the jit compiler
547
548 *******************************************************************************/
549
550 java_objectheader *new_negativearraysizeexception()
551 {
552         java_objectheader *e;
553
554         e = new_exception(string_java_lang_NegativeArraySizeException);
555
556         if (!e)
557                 return *exceptionptr;
558
559         return e;
560 }
561
562
563 /* new_nullpointerexception ****************************************************
564
565    generates a java.lang.NullPointerException for the jit compiler
566
567 *******************************************************************************/
568
569 java_objectheader *new_nullpointerexception()
570 {
571         java_objectheader *e;
572
573         e = new_exception(string_java_lang_NullPointerException);
574
575         if (!e)
576                 return *exceptionptr;
577
578         return e;
579 }
580
581
582 /*
583  * These are local overrides for various environment variables in Emacs.
584  * Please do not remove this and leave it at the end of the file, where
585  * Emacs will automagically detect them.
586  * ---------------------------------------------------------------------
587  * Local variables:
588  * mode: c
589  * indent-tabs-mode: t
590  * c-basic-offset: 4
591  * tab-width: 4
592  * End:
593  */