19be6b1cfeb7bd1a4e65b67b68304f502f6a8504
[cacao.git] / src / vm / exceptions.c
1 /* src/vm/exceptions.c - exception related functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28             Edwin Steiner
29
30    $Id: exceptions.c 6244 2006-12-27 15:15:31Z twisti $
31
32 */
33
34
35 #include "config.h"
36
37 #include <assert.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include <stdlib.h>
41
42 #include "vm/types.h"
43
44 #include "mm/memory.h"
45 #include "native/jni.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_String.h"
48 #include "native/include/java_lang_Throwable.h"
49 #include "toolbox/logging.h"
50 #include "toolbox/util.h"
51 #include "vm/class.h"
52 #include "vm/exceptions.h"
53 #include "vm/global.h"
54 #include "vm/loader.h"
55 #include "vm/options.h"
56 #include "vm/stringlocal.h"
57 #include "vm/vm.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/methodheader.h"
61
62
63 /* for raising exceptions from native methods *********************************/
64
65 #if !defined(ENABLE_THREADS)
66 java_objectheader *_no_threads_exceptionptr = NULL;
67 #endif
68
69
70 /* init_system_exceptions ******************************************************
71
72    Load and link exceptions used in the system.
73
74 *******************************************************************************/
75
76 bool exceptions_init(void)
77 {
78         /* java/lang/Throwable */
79
80         if (!(class_java_lang_Throwable =
81                   load_class_bootstrap(utf_java_lang_Throwable)) ||
82                 !link_class(class_java_lang_Throwable))
83                 return false;
84
85         /* java/lang/Error */
86
87         if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
88                 !link_class(class_java_lang_Error))
89                 return false;
90
91 #if defined(ENABLE_JAVASE)
92         /* java/lang/AbstractMethodError */
93
94         if (!(class_java_lang_AbstractMethodError =
95                   load_class_bootstrap(utf_java_lang_AbstractMethodError)) ||
96                 !link_class(class_java_lang_AbstractMethodError))
97                 return false;
98
99         /* java/lang/LinkageError */
100
101         if (!(class_java_lang_LinkageError =
102                   load_class_bootstrap(utf_java_lang_LinkageError)) ||
103                 !link_class(class_java_lang_LinkageError))
104                 return false;
105 #endif
106
107         /* java/lang/NoClassDefFoundError */
108
109         if (!(class_java_lang_NoClassDefFoundError =
110                   load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
111                 !link_class(class_java_lang_NoClassDefFoundError))
112                 return false;
113
114 #if defined(ENABLE_JAVASE)
115         /* java/lang/NoSuchMethodError */
116
117         if (!(class_java_lang_NoSuchMethodError =
118                   load_class_bootstrap(utf_java_lang_NoSuchMethodError)) ||
119                 !link_class(class_java_lang_NoSuchMethodError))
120                 return false;
121 #endif
122
123         /* java/lang/OutOfMemoryError */
124
125         if (!(class_java_lang_OutOfMemoryError =
126                   load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
127                 !link_class(class_java_lang_OutOfMemoryError))
128                 return false;
129
130         /* java/lang/VirtualMachineError */
131
132         if (!(class_java_lang_VirtualMachineError =
133                   load_class_bootstrap(utf_java_lang_VirtualMachineError)) ||
134                 !link_class(class_java_lang_VirtualMachineError))
135                 return false;
136
137
138         /* java/lang/Exception */
139
140         if (!(class_java_lang_Exception =
141                   load_class_bootstrap(utf_java_lang_Exception)) ||
142                 !link_class(class_java_lang_Exception))
143                 return false;
144
145         /* java/lang/ClassCastException */
146
147         if (!(class_java_lang_ClassCastException =
148                   load_class_bootstrap(utf_java_lang_ClassCastException)) ||
149                 !link_class(class_java_lang_ClassCastException))
150                 return false;
151
152         /* java/lang/ClassNotFoundException */
153
154         if (!(class_java_lang_ClassNotFoundException =
155                   load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
156                 !link_class(class_java_lang_ClassNotFoundException))
157                 return false;
158
159         /* java/lang/IllegalArgumentException */
160
161         if (!(class_java_lang_IllegalArgumentException =
162                   load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
163                 !link_class(class_java_lang_IllegalArgumentException))
164                 return false;
165
166         /* java/lang/IllegalMonitorStateException */
167
168         if (!(class_java_lang_IllegalMonitorStateException =
169                   load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
170                 !link_class(class_java_lang_IllegalMonitorStateException))
171                 return false;
172
173         /* java/lang/NullPointerException */
174
175         if (!(class_java_lang_NullPointerException =
176                   load_class_bootstrap(utf_java_lang_NullPointerException)) ||
177                 !link_class(class_java_lang_NullPointerException))
178                 return false;
179
180
181 #if defined(WITH_CLASSPATH_GNU)
182         /* java/lang/VMThrowable */
183
184         if (!(class_java_lang_VMThrowable =
185                   load_class_bootstrap(utf_java_lang_VMThrowable)) ||
186                 !link_class(class_java_lang_VMThrowable))
187                 return false;
188 #endif
189
190         return true;
191 }
192
193
194 static void throw_exception_exit_intern(bool doexit)
195 {
196         java_objectheader *xptr;
197         classinfo *c;
198         methodinfo *pss;
199
200         xptr = *exceptionptr;
201
202         if (xptr) {
203                 /* clear exception, because we are calling jit code again */
204                 *exceptionptr = NULL;
205
206                 c = xptr->vftbl->class;
207
208                 pss = class_resolveclassmethod(c,
209                                                                            utf_printStackTrace,
210                                                                            utf_void__void,
211                                                                            class_java_lang_Object,
212                                                                            false);
213
214                 /* print the stacktrace */
215
216                 if (pss) {
217                         (void) vm_call_method(pss, xptr);
218
219                         /* This normally means, we are EXTREMLY out of memory or have a   */
220                         /* serious problem while printStackTrace. But may be another      */
221                         /* exception, so print it.                                        */
222
223                         if (*exceptionptr) {
224                                 java_lang_Throwable *t;
225
226                                 t = (java_lang_Throwable *) *exceptionptr;
227
228                                 fprintf(stderr, "Exception while printStackTrace(): ");
229                                 utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name);
230
231                                 if (t->detailMessage) {
232                                         char *buf;
233
234                                         buf = javastring_tochar((java_objectheader *) t->detailMessage);
235                                         fprintf(stderr, ": %s", buf);
236                                         MFREE(buf, char, strlen(buf));
237                                 }
238                                         
239                                 fprintf(stderr, "\n");
240                         }
241
242                 } else {
243                         utf_fprint_printable_ascii_classname(stderr, c->name);
244                         fprintf(stderr, ": printStackTrace()V not found!\n");
245                 }
246
247                 fflush(stderr);
248
249                 /* good bye! */
250
251                 if (doexit)
252                         exit(1);
253         }
254 }
255
256
257 void throw_exception(void)
258 {
259         throw_exception_exit_intern(false);
260 }
261
262
263 void throw_exception_exit(void)
264 {
265         throw_exception_exit_intern(true);
266 }
267
268
269 void throw_main_exception(void)
270 {
271         fprintf(stderr, "Exception in thread \"main\" ");
272         fflush(stderr);
273
274         throw_exception_exit_intern(false);
275 }
276
277
278 void throw_main_exception_exit(void)
279 {
280         fprintf(stderr, "Exception in thread \"main\" ");
281         fflush(stderr);
282
283         throw_exception_exit_intern(true);
284 }
285
286
287 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
288 {
289         s4 i;
290         char *tmp;
291         s4 len;
292         va_list ap;
293
294         len = strlen(exception);
295         tmp = MNEW(char, len + 1);
296         strncpy(tmp, exception, len);
297         tmp[len] = '\0';
298
299         /* convert to classname */
300
301         for (i = len - 1; i >= 0; i--)
302                 if (tmp[i] == '/') tmp[i] = '.';
303
304         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
305
306         MFREE(tmp, char, len);
307
308         if (strlen(message) > 0) {
309                 fprintf(stderr, ": ");
310
311                 va_start(ap, message);
312                 vfprintf(stderr, message, ap);
313                 va_end(ap);
314         }
315
316         fprintf(stderr, "\n");
317         fflush(stderr);
318
319         /* good bye! */
320
321         exit(1);
322 }
323
324
325 /* exceptions_throw_outofmemory_exit *******************************************
326
327    Just print an: java.lang.InternalError: Out of memory
328
329 *******************************************************************************/
330
331 void exceptions_throw_outofmemory_exit(void)
332 {
333         throw_cacao_exception_exit(string_java_lang_InternalError,
334                                                            "Out of memory");
335 }
336
337
338 /* new_exception ***************************************************************
339
340    Creates an exception object with the given name and initalizes it.
341
342    IN:
343       classname....class name in UTF-8
344
345    RETURN VALUE:
346       an exception pointer (in any case -- either it is the newly created
347           exception, or an exception thrown while trying to create it).
348
349 *******************************************************************************/
350
351 java_objectheader *new_exception(const char *classname)
352 {
353         java_objectheader *o;
354         classinfo         *c;
355
356         if (!(c = load_class_bootstrap(utf_new_char(classname))))
357                 return *exceptionptr;
358
359         o = native_new_and_init(c);
360
361         if (!o)
362                 return *exceptionptr;
363
364         return o;
365 }
366
367
368 /* new_exception_message *******************************************************
369
370    Creates an exception object with the given name and initalizes it
371    with the given char message.
372
373    IN:
374       classname....class name in UTF-8
375           message......message in UTF-8
376
377    RETURN VALUE:
378       an exception pointer (in any case -- either it is the newly created
379           exception, or an exception thrown while trying to create it).
380
381 *******************************************************************************/
382
383 java_objectheader *new_exception_message(const char *classname,
384                                                                                  const char *message)
385 {
386         java_lang_String *s;
387
388         s = javastring_new_from_utf_string(message);
389         if (!s)
390                 return *exceptionptr;
391
392         return new_exception_javastring(classname, s);
393 }
394
395
396 /* new_exception_throwable *****************************************************
397
398    Creates an exception object with the given name and initalizes it
399    with the given java/lang/Throwable exception.
400
401    IN:
402       classname....class name in UTF-8
403           throwable....the given Throwable
404
405    RETURN VALUE:
406       an exception pointer (in any case -- either it is the newly created
407           exception, or an exception thrown while trying to create it).
408
409 *******************************************************************************/
410
411 java_objectheader *new_exception_throwable(const char *classname,
412                                                                                    java_lang_Throwable *throwable)
413 {
414         java_objectheader *o;
415         classinfo         *c;
416    
417         if (!(c = load_class_bootstrap(utf_new_char(classname))))
418                 return *exceptionptr;
419
420         o = native_new_and_init_throwable(c, throwable);
421
422         if (!o)
423                 return *exceptionptr;
424
425         return o;
426 }
427
428
429 /* new_exception_utfmessage ****************************************************
430
431    Creates an exception object with the given name and initalizes it
432    with the given utf message.
433
434    IN:
435       classname....class name in UTF-8
436           message......the message as an utf *
437
438    RETURN VALUE:
439       an exception pointer (in any case -- either it is the newly created
440           exception, or an exception thrown while trying to create it).
441
442 *******************************************************************************/
443
444 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
445 {
446         java_lang_String *s;
447
448         s = javastring_new(message);
449         if (!s)
450                 return *exceptionptr;
451
452         return new_exception_javastring(classname, s);
453 }
454
455
456 /* new_exception_javastring ****************************************************
457
458    Creates an exception object with the given name and initalizes it
459    with the given java/lang/String message.
460
461    IN:
462       classname....class name in UTF-8
463           message......the message as a java.lang.String
464
465    RETURN VALUE:
466       an exception pointer (in any case -- either it is the newly created
467           exception, or an exception thrown while trying to create it).
468
469 *******************************************************************************/
470
471 java_objectheader *new_exception_javastring(const char *classname,
472                                                                                         java_lang_String *message)
473 {
474         java_objectheader *o;
475         classinfo         *c;
476    
477         if (!(c = load_class_bootstrap(utf_new_char(classname))))
478                 return *exceptionptr;
479
480         o = native_new_and_init_string(c, message);
481
482         if (!o)
483                 return *exceptionptr;
484
485         return o;
486 }
487
488
489 /* new_exception_int ***********************************************************
490
491    Creates an exception object with the given name and initalizes it
492    with the given int value.
493
494    IN:
495       classname....class name in UTF-8
496           i............the integer
497
498    RETURN VALUE:
499       an exception pointer (in any case -- either it is the newly created
500           exception, or an exception thrown while trying to create it).
501
502 *******************************************************************************/
503
504 java_objectheader *new_exception_int(const char *classname, s4 i)
505 {
506         java_objectheader *o;
507         classinfo         *c;
508    
509         if (!(c = load_class_bootstrap(utf_new_char(classname))))
510                 return *exceptionptr;
511
512         o = native_new_and_init_int(c, i);
513
514         if (!o)
515                 return *exceptionptr;
516
517         return o;
518 }
519
520
521 /* exceptions_new_abstractmethoderror ******************************************
522
523    Generates a java.lang.AbstractMethodError for the VM.
524
525 *******************************************************************************/
526
527 #if defined(ENABLE_JAVASE)
528 java_objectheader *exceptions_new_abstractmethoderror(void)
529 {
530         java_objectheader *e;
531
532         e = native_new_and_init(class_java_lang_AbstractMethodError);
533
534         if (e == NULL)
535                 return *exceptionptr;
536
537         return e;
538 }
539 #endif
540
541
542 /* exceptions_asm_new_abstractmethoderror **************************************
543
544    Generates a java.lang.AbstractMethodError for
545    asm_abstractmethoderror.
546
547 *******************************************************************************/
548
549 #if defined(ENABLE_JAVASE)
550 java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
551 {
552         stackframeinfo     sfi;
553         java_objectheader *e;
554
555         /* create the stackframeinfo (XPC is equal to RA) */
556
557         stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
558
559         /* create the exception */
560
561         e = exceptions_new_abstractmethoderror();
562
563         /* remove the stackframeinfo */
564
565         stacktrace_remove_stackframeinfo(&sfi);
566
567         return e;
568 }
569 #endif
570
571
572 /* exceptions_throw_abstractmethoderror ****************************************
573
574    Generates a java.lang.AbstractMethodError for the VM and throws it.
575
576 *******************************************************************************/
577
578 #if defined(ENABLE_JAVASE)
579 void exceptions_throw_abstractmethoderror(void)
580 {
581         *exceptionptr = exceptions_new_abstractmethoderror();
582 }
583 #endif
584
585
586 /* new_classformaterror ********************************************************
587
588    generates a java.lang.ClassFormatError for the classloader
589
590    IN:
591       c............the class in which the error was found
592           message......UTF-8 format string
593
594    RETURN VALUE:
595       an exception pointer (in any case -- either it is the newly created
596           exception, or an exception thrown while trying to create it).
597
598 *******************************************************************************/
599
600 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
601 {
602         java_objectheader *o;
603         char              *msg;
604         s4                 msglen;
605         va_list            ap;
606
607         /* calculate message length */
608
609         msglen = 0;
610
611         if (c)
612                 msglen += utf_bytes(c->name) + strlen(" (");
613
614         va_start(ap, message);
615         msglen += get_variable_message_length(message, ap);
616         va_end(ap);
617
618         if (c)
619                 msglen += strlen(")");
620
621         msglen += strlen("0");
622
623         /* allocate a buffer */
624
625         msg = MNEW(char, msglen);
626
627         /* print message into allocated buffer */
628
629         if (c) {
630                 utf_copy_classname(msg, c->name);
631                 strcat(msg, " (");
632         }
633
634         va_start(ap, message);
635         vsprintf(msg + strlen(msg), message, ap);
636         va_end(ap);
637
638         if (c)
639                 strcat(msg, ")");
640
641         o = new_exception_message(string_java_lang_ClassFormatError, msg);
642
643         MFREE(msg, char, msglen);
644
645         return o;
646 }
647
648
649 /* exceptions_throw_classformaterror *******************************************
650
651    Generate a java.lang.ClassFormatError for the VM system and throw it.
652
653    IN:
654       c............the class in which the error was found
655           message......UTF-8 format string
656
657    RETURN VALUE:
658       an exception pointer (in any case -- either it is the newly created
659           exception, or an exception thrown while trying to create it).
660
661 *******************************************************************************/
662
663 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
664 {
665         va_list ap;
666
667         va_start(ap, message);
668         *exceptionptr = new_classformaterror(c, message, ap);
669         va_end(ap);
670 }
671
672
673 /* new_classnotfoundexception **************************************************
674
675    Generates a java.lang.ClassNotFoundException for the classloader.
676
677    IN:
678       name.........name of the class not found as a utf *
679
680    RETURN VALUE:
681       an exception pointer (in any case -- either it is the newly created
682           exception, or an exception thrown while trying to create it).
683
684 *******************************************************************************/
685
686 java_objectheader *new_classnotfoundexception(utf *name)
687 {
688         java_objectheader *o;
689         java_lang_String  *s;
690
691         s = javastring_new(name);
692         if (!s)
693                 return *exceptionptr;
694
695         o = native_new_and_init_string(class_java_lang_ClassNotFoundException, s);
696
697         if (!o)
698                 return *exceptionptr;
699
700         return o;
701 }
702
703
704 /* new_noclassdeffounderror ****************************************************
705
706    Generates a java.lang.NoClassDefFoundError
707
708    IN:
709       name.........name of the class not found as a utf *
710
711    RETURN VALUE:
712       an exception pointer (in any case -- either it is the newly created
713           exception, or an exception thrown while trying to create it).
714
715 *******************************************************************************/
716
717 java_objectheader *new_noclassdeffounderror(utf *name)
718 {
719         java_objectheader *o;
720         java_lang_String  *s;
721
722         s = javastring_new(name);
723         if (!s)
724                 return *exceptionptr;
725
726         o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, s);
727
728         if (!o)
729                 return *exceptionptr;
730
731         return o;
732 }
733
734
735 /* classnotfoundexception_to_noclassdeffounderror ******************************
736
737    Check the *exceptionptr for a ClassNotFoundException. If it is one,
738    convert it to a NoClassDefFoundError.
739
740 *******************************************************************************/
741
742 void classnotfoundexception_to_noclassdeffounderror(void)
743 {
744         java_objectheader *xptr;
745         java_objectheader *cause;
746
747         /* get the cause */
748
749         cause = *exceptionptr;
750
751         /* convert ClassNotFoundException's to NoClassDefFoundError's */
752
753         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
754                 /* clear exception, because we are calling jit code again */
755
756                 *exceptionptr = NULL;
757
758                 /* create new error */
759
760                 xptr =
761                         new_exception_javastring(string_java_lang_NoClassDefFoundError,
762                                         ((java_lang_Throwable *) cause)->detailMessage);
763
764                 /* we had an exception while creating the error */
765
766                 if (*exceptionptr)
767                         return;
768
769                 /* set new exception */
770
771                 *exceptionptr = xptr;
772         }
773 }
774
775
776 /* new_internalerror ***********************************************************
777
778    Generates a java.lang.InternalError for the VM.
779
780    IN:
781       message......UTF-8 message format string
782
783    RETURN VALUE:
784       an exception pointer (in any case -- either it is the newly created
785           exception, or an exception thrown while trying to create it).
786
787 *******************************************************************************/
788
789 java_objectheader *new_internalerror(const char *message, ...)
790 {
791         java_objectheader *o;
792         va_list            ap;
793         char              *msg;
794         s4                 msglen;
795
796         /* calculate exception message length */
797
798         va_start(ap, message);
799         msglen = get_variable_message_length(message, ap);
800         va_end(ap);
801
802         /* allocate memory */
803
804         msg = MNEW(char, msglen);
805
806         /* generate message */
807
808         va_start(ap, message);
809         vsprintf(msg, message, ap);
810         va_end(ap);
811
812         /* create exception object */
813
814         o = new_exception_message(string_java_lang_InternalError, msg);
815
816         /* free memory */
817
818         MFREE(msg, char, msglen);
819
820         return o;
821 }
822
823
824 /* exceptions_throw_internalerror **********************************************
825
826    Generates a java.lang.InternalError for the VM.
827
828    IN:
829       message......UTF-8 message format string
830
831 *******************************************************************************/
832
833 void exceptions_throw_internalerror(const char *message, ...)
834 {
835         va_list ap;
836
837         va_start(ap, message);
838         *exceptionptr = new_internalerror(message, ap);
839         va_end(ap);
840 }
841
842
843 /* exceptions_new_linkageerror *************************************************
844
845    Generates a java.lang.LinkageError with an error message.
846
847    IN:
848       message......UTF-8 message
849           c............class related to the error. If this is != NULL
850                        the name of c is appended to the error message.
851
852    RETURN VALUE:
853       an exception pointer (in any case -- either it is the newly created
854           exception, or an exception thrown while trying to create it).
855
856 *******************************************************************************/
857
858 java_objectheader *exceptions_new_linkageerror(const char *message,
859                                                                                            classinfo *c)
860 {
861         java_objectheader *o;
862         char              *msg;
863         s4                 msglen;
864
865         /* calculate exception message length */
866
867         msglen = strlen(message) + 1;
868         if (c) {
869                 msglen += utf_bytes(c->name);
870         }
871                 
872         /* allocate memory */
873
874         msg = MNEW(char, msglen);
875
876         /* generate message */
877
878         strcpy(msg,message);
879         if (c) {
880                 utf_cat_classname(msg, c->name);
881         }
882
883         o = native_new_and_init_string(class_java_lang_LinkageError,
884                                                                    javastring_new_from_utf_string(msg));
885
886         /* free memory */
887
888         MFREE(msg, char, msglen);
889
890         if (!o)
891                 return *exceptionptr;
892
893         return o;
894 }
895
896
897 /* exceptions_new_nosuchmethoderror ********************************************
898
899    Generates a java.lang.NoSuchMethodError with an error message.
900
901    IN:
902       c............class in which the method was not found
903           name.........name of the method
904           desc.........descriptor of the method
905
906    RETURN VALUE:
907       an exception pointer (in any case -- either it is the newly created
908           exception, or an exception thrown while trying to create it).
909
910 *******************************************************************************/
911
912 #if defined(ENABLE_JAVASE)
913 java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
914                                                                                                         utf *name, utf *desc)
915 {
916         java_objectheader *o;
917         char              *msg;
918         s4                 msglen;
919
920         /* calculate exception message length */
921
922         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
923                 utf_bytes(desc) + strlen("0");
924
925         /* allocate memory */
926
927         msg = MNEW(char, msglen);
928
929         /* generate message */
930
931         utf_copy_classname(msg, c->name);
932         strcat(msg, ".");
933         utf_cat(msg, name);
934         utf_cat(msg, desc);
935
936         o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
937                                                                    javastring_new_from_utf_string(msg));
938
939         /* free memory */
940
941         MFREE(msg, char, msglen);
942
943         if (o == NULL)
944                 return *exceptionptr;
945
946         return o;
947 }
948 #endif
949
950
951 /* exceptions_throw_nosuchmethoderror ******************************************
952
953    Generates a java.lang.NoSuchMethodError with an error message.
954
955    IN:
956       c............class in which the method was not found
957           name.........name of the method
958           desc.........descriptor of the method
959
960 *******************************************************************************/
961
962 #if defined(ENABLE_JAVASE)
963 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
964 {
965         *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
966 }
967 #endif
968
969
970 /* new_unsupportedclassversionerror ********************************************
971
972    Generate a java.lang.UnsupportedClassVersionError for the classloader
973
974    IN:
975       c............class in which the method was not found
976           message......UTF-8 format string
977
978    RETURN VALUE:
979       an exception pointer (in any case -- either it is the newly created
980           exception, or an exception thrown while trying to create it).
981
982 *******************************************************************************/
983
984 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
985 {
986         java_objectheader *o;
987         va_list            ap;
988         char              *msg;
989     s4                 msglen;
990
991         /* calculate exception message length */
992
993         msglen = utf_bytes(c->name) + strlen(" (") + strlen(")") + strlen("0");
994
995         va_start(ap, message);
996         msglen += get_variable_message_length(message, ap);
997         va_end(ap);
998
999         /* allocate memory */
1000
1001         msg = MNEW(char, msglen);
1002
1003         /* generate message */
1004
1005         utf_copy_classname(msg, c->name);
1006         strcat(msg, " (");
1007
1008         va_start(ap, message);
1009         vsprintf(msg + strlen(msg), message, ap);
1010         va_end(ap);
1011
1012         strcat(msg, ")");
1013
1014         /* create exception object */
1015
1016         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
1017                                                           msg);
1018
1019         /* free memory */
1020
1021         MFREE(msg, char, msglen);
1022
1023         return o;
1024 }
1025
1026
1027 /* exceptions_new_verifyerror **************************************************
1028
1029    Generates a java.lang.VerifyError for the JIT compiler.
1030
1031    IN:
1032       m............method in which the error was found
1033           message......UTF-8 format string
1034
1035    RETURN VALUE:
1036       an exception pointer (in any case -- either it is the newly created
1037           exception, or an exception thrown while trying to create it).
1038
1039 *******************************************************************************/
1040
1041 java_objectheader *exceptions_new_verifyerror(methodinfo *m,
1042                                                                                           const char *message, ...)
1043 {
1044         java_objectheader *o;
1045         va_list            ap;
1046         char              *msg;
1047         s4                 msglen;
1048
1049         useinlining = false; /* at least until sure inlining works with exceptions*/
1050
1051         /* calculate exception message length */
1052
1053         msglen = 0;
1054
1055         if (m)
1056                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1057                         strlen(", method: ") + utf_bytes(m->name) +
1058                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1059                         strlen(") ") + strlen("0");
1060
1061         va_start(ap, message);
1062         msglen += get_variable_message_length(message, ap);
1063         va_end(ap);
1064
1065         /* allocate memory */
1066
1067         msg = MNEW(char, msglen);
1068
1069         /* generate message */
1070
1071         if (m) {
1072                 strcpy(msg, "(class: ");
1073                 utf_cat_classname(msg, m->class->name);
1074                 strcat(msg, ", method: ");
1075                 utf_cat(msg, m->name);
1076                 strcat(msg, " signature: ");
1077                 utf_cat(msg, m->descriptor);
1078                 strcat(msg, ") ");
1079         }
1080
1081         va_start(ap, message);
1082         vsprintf(msg + strlen(msg), message, ap);
1083         va_end(ap);
1084
1085         /* create exception object */
1086
1087         o = new_exception_message(string_java_lang_VerifyError, msg);
1088
1089         /* free memory */
1090
1091         MFREE(msg, char, msglen);
1092
1093         return o;
1094 }
1095
1096
1097 /* exceptions_throw_verifyerror ************************************************
1098
1099    Throws a java.lang.VerifyError for the VM system.
1100
1101 *******************************************************************************/
1102
1103 void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
1104 {
1105         *exceptionptr = exceptions_new_verifyerror(m, message);
1106 }
1107
1108
1109 /* exceptions_throw_verifyerror_for_stack **************************************
1110
1111    throws a java.lang.VerifyError for an invalid stack slot type
1112
1113    IN:
1114       m............method in which the error was found
1115           type.........the expected type
1116
1117    RETURN VALUE:
1118       an exception pointer (in any case -- either it is the newly created
1119           exception, or an exception thrown while trying to create it).
1120
1121 *******************************************************************************/
1122
1123 void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
1124 {
1125         java_objectheader *o;
1126         char              *msg;
1127         s4                 msglen;
1128         char              *typename;
1129
1130         /* calculate exception message length */
1131
1132         msglen = 0;
1133
1134         if (m)
1135                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1136                         strlen(", method: ") + utf_bytes(m->name) +
1137                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1138                         strlen(") Expecting to find longest-------typename on stack") 
1139                         + strlen("0");
1140
1141         /* allocate memory */
1142
1143         msg = MNEW(char, msglen);
1144
1145         /* generate message */
1146
1147         if (m) {
1148                 strcpy(msg, "(class: ");
1149                 utf_cat_classname(msg, m->class->name);
1150                 strcat(msg, ", method: ");
1151                 utf_cat(msg, m->name);
1152                 strcat(msg, " signature: ");
1153                 utf_cat(msg, m->descriptor);
1154                 strcat(msg, ") ");
1155         }
1156         else {
1157                 msg[0] = 0;
1158         }
1159
1160         strcat(msg,"Expecting to find ");
1161         switch (type) {
1162                 case TYPE_INT: typename = "integer"; break;
1163                 case TYPE_LNG: typename = "long"; break;
1164                 case TYPE_FLT: typename = "float"; break;
1165                 case TYPE_DBL: typename = "double"; break;
1166                 case TYPE_ADR: typename = "object/array"; break;
1167                 case TYPE_RET: typename = "returnAddress"; break;
1168                 default:       typename = "<INVALID>"; assert(0); break;
1169         }
1170         strcat(msg, typename);
1171         strcat(msg, " on stack");
1172
1173         /* create exception object */
1174
1175         o = new_exception_message(string_java_lang_VerifyError, msg);
1176
1177         /* free memory */
1178
1179         MFREE(msg, char, msglen);
1180
1181         *exceptionptr = o;
1182 }
1183
1184
1185 /* exceptions_new_virtualmachineerror ******************************************
1186
1187    Generates a java.lang.VirtualMachineError for the VM system.
1188
1189 *******************************************************************************/
1190
1191 java_objectheader *exceptions_new_virtualmachineerror(void)
1192 {
1193         java_objectheader *e;
1194
1195         e = native_new_and_init(class_java_lang_VirtualMachineError);
1196
1197         if (e == NULL)
1198                 return *exceptionptr;
1199
1200         return e;
1201 }
1202
1203
1204 /* exceptions_throw_virtualmachineerror ****************************************
1205
1206    Throws a java.lang.VirtualMachineError for the VM system.
1207
1208 *******************************************************************************/
1209
1210 void exceptions_throw_virtualmachineerror(void)
1211 {
1212         *exceptionptr = exceptions_new_virtualmachineerror();
1213 }
1214
1215
1216 /* new_arithmeticexception *****************************************************
1217
1218    Generates a java.lang.ArithmeticException for the jit compiler.
1219
1220 *******************************************************************************/
1221
1222 java_objectheader *new_arithmeticexception(void)
1223 {
1224         java_objectheader *e;
1225
1226         e = new_exception_message(string_java_lang_ArithmeticException,
1227                                                           string_java_lang_ArithmeticException_message);
1228
1229         if (!e)
1230                 return *exceptionptr;
1231
1232         return e;
1233 }
1234
1235
1236 /* exceptions_new_arrayindexoutofboundsexception *******************************
1237
1238    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1239    system.
1240
1241 *******************************************************************************/
1242
1243 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
1244 {
1245         java_objectheader *e;
1246         methodinfo        *m;
1247         java_objectheader *o;
1248         java_lang_String  *s;
1249
1250         /* convert the index into a String, like Sun does */
1251
1252         m = class_resolveclassmethod(class_java_lang_String,
1253                                                                  utf_new_char("valueOf"),
1254                                                                  utf_new_char("(I)Ljava/lang/String;"),
1255                                                                  class_java_lang_Object,
1256                                                                  true);
1257
1258         if (m == NULL)
1259                 return *exceptionptr;
1260
1261         o = vm_call_method(m, NULL, index);
1262
1263         s = (java_lang_String *) o;
1264
1265         if (s == NULL)
1266                 return *exceptionptr;
1267
1268         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
1269                                                                  s);
1270
1271         if (e == NULL)
1272                 return *exceptionptr;
1273
1274         return e;
1275 }
1276
1277
1278 /* exceptions_throw_arrayindexoutofboundsexception *****************************
1279
1280    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1281    system.
1282
1283 *******************************************************************************/
1284
1285 void exceptions_throw_arrayindexoutofboundsexception(void)
1286 {
1287         java_objectheader *e;
1288
1289         e = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
1290
1291         if (!e)
1292                 return;
1293
1294         *exceptionptr = e;
1295 }
1296
1297
1298 /* exceptions_new_arraystoreexception ******************************************
1299
1300    Generates a java.lang.ArrayStoreException for the VM compiler.
1301
1302 *******************************************************************************/
1303
1304 java_objectheader *exceptions_new_arraystoreexception(void)
1305 {
1306         java_objectheader *e;
1307
1308         e = new_exception(string_java_lang_ArrayStoreException);
1309 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
1310
1311         if (!e)
1312                 return *exceptionptr;
1313
1314         return e;
1315 }
1316
1317
1318 /* exceptions_throw_arraystoreexception ****************************************
1319
1320    Generates a java.lang.ArrayStoreException for the VM system and
1321    throw it in the VM system.
1322
1323 *******************************************************************************/
1324
1325 void exceptions_throw_arraystoreexception(void)
1326 {
1327         *exceptionptr = exceptions_new_arraystoreexception();
1328 }
1329
1330
1331 /* exceptions_new_classcastexception *******************************************
1332
1333    Generates a java.lang.ClassCastException for the JIT compiler.
1334
1335 *******************************************************************************/
1336
1337 java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
1338 {
1339         java_objectheader *e;
1340         utf               *classname;
1341         java_lang_String  *s;
1342
1343         classname = o->vftbl->class->name;
1344
1345         s = javastring_new(classname);
1346
1347         e = native_new_and_init_string(class_java_lang_ClassCastException, s);
1348
1349         if (e == NULL)
1350                 return *exceptionptr;
1351
1352         return e;
1353 }
1354
1355
1356 /* exceptions_new_illegalargumentexception *************************************
1357
1358    Generates a java.lang.IllegalArgumentException for the VM system.
1359
1360 *******************************************************************************/
1361
1362 java_objectheader *new_illegalargumentexception(void)
1363 {
1364         java_objectheader *e;
1365
1366         e = native_new_and_init(class_java_lang_IllegalArgumentException);
1367
1368         if (!e)
1369                 return *exceptionptr;
1370
1371         return e;
1372 }
1373
1374
1375 /* exceptions_throw_illegalargumentexception ***********************************
1376
1377    Generates a java.lang.IllegalArgumentException for the VM system
1378    and throw it in the VM system.
1379
1380 *******************************************************************************/
1381
1382 void exceptions_throw_illegalargumentexception(void)
1383 {
1384         *exceptionptr = new_illegalargumentexception();
1385 }
1386
1387
1388 /* exceptions_new_illegalmonitorstateexception *********************************
1389
1390    Generates a java.lang.IllegalMonitorStateException for the VM
1391    thread system.
1392
1393 *******************************************************************************/
1394
1395 java_objectheader *exceptions_new_illegalmonitorstateexception(void)
1396 {
1397         java_objectheader *e;
1398
1399         e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
1400
1401         if (e == NULL)
1402                 return *exceptionptr;
1403
1404         return e;
1405 }
1406
1407
1408 /* exceptions_throw_illegalmonitorstateexception *******************************
1409
1410    Generates a java.lang.IllegalMonitorStateException for the VM
1411    system and throw it in the VM system.
1412
1413 *******************************************************************************/
1414
1415 void exceptions_throw_illegalmonitorstateexception(void)
1416 {
1417         *exceptionptr = exceptions_new_illegalmonitorstateexception();
1418 }
1419
1420
1421 /* exceptions_new_negativearraysizeexception ***********************************
1422
1423    Generates a java.lang.NegativeArraySizeException for the VM system.
1424
1425 *******************************************************************************/
1426
1427 java_objectheader *new_negativearraysizeexception(void)
1428 {
1429         java_objectheader *e;
1430
1431         e = new_exception(string_java_lang_NegativeArraySizeException);
1432
1433         if (!e)
1434                 return *exceptionptr;
1435
1436         return e;
1437 }
1438
1439
1440 /* exceptions_throw_negativearraysizeexception *********************************
1441
1442    Generates a java.lang.NegativeArraySizeException for the VM system.
1443
1444 *******************************************************************************/
1445
1446 void exceptions_throw_negativearraysizeexception(void)
1447 {
1448         *exceptionptr = new_negativearraysizeexception();
1449 }
1450
1451
1452 /* exceptions_new_nullpointerexception *****************************************
1453
1454    Generates a java.lang.NullPointerException for the VM system.
1455
1456 *******************************************************************************/
1457
1458 java_objectheader *exceptions_new_nullpointerexception(void)
1459 {
1460         java_objectheader *e;
1461
1462         e = native_new_and_init(class_java_lang_NullPointerException);
1463
1464         if (e == NULL)
1465                 return *exceptionptr;
1466
1467         return e;
1468 }
1469
1470
1471 /* exceptions_throw_nullpointerexception ***************************************
1472
1473    Generates a java.lang.NullPointerException for the VM system and
1474    throw it in the VM system.
1475
1476 *******************************************************************************/
1477
1478 void exceptions_throw_nullpointerexception(void)
1479 {
1480         *exceptionptr = exceptions_new_nullpointerexception();
1481 }
1482
1483
1484 /* exceptions_new_stringindexoutofboundsexception ******************************
1485
1486    Generates a java.lang.StringIndexOutOfBoundsException for the VM
1487    system.
1488
1489 *******************************************************************************/
1490
1491 java_objectheader *exceptions_new_stringindexoutofboundsexception(void)
1492 {
1493         java_objectheader *e;
1494
1495         e = new_exception(string_java_lang_StringIndexOutOfBoundsException);
1496
1497         if (e == NULL)
1498                 return *exceptionptr;
1499
1500         return e;
1501 }
1502
1503
1504 /* exceptions_throw_stringindexoutofboundsexception ****************************
1505
1506    Throws a java.lang.StringIndexOutOfBoundsException for the VM
1507    system.
1508
1509 *******************************************************************************/
1510
1511 void exceptions_throw_stringindexoutofboundsexception(void)
1512 {
1513         *exceptionptr = exceptions_new_stringindexoutofboundsexception();
1514 }
1515
1516
1517 /* exceptions_get_and_clear_exception ******************************************
1518
1519    Gets the exception pointer of the current thread and clears it.
1520    This function may return NULL.
1521
1522 *******************************************************************************/
1523
1524 java_objectheader *exceptions_get_and_clear_exception(void)
1525 {
1526         java_objectheader **p;
1527         java_objectheader  *e;
1528
1529         /* get the pointer of the exception pointer */
1530
1531         p = exceptionptr;
1532
1533         /* get the exception */
1534
1535         e = *p;
1536
1537         /* and clear the exception */
1538
1539         *p = NULL;
1540
1541         /* return the exception */
1542
1543         return e;
1544 }
1545
1546
1547 /* exceptions_handle_exception *************************************************
1548
1549    Try to find an exception handler for the given exception and return it.
1550    If no handler is found, exit the monitor of the method (if any)
1551    and return NULL.
1552
1553    IN:
1554       xptr.........the exception object
1555           xpc..........PC of where the exception was thrown
1556           pv...........Procedure Value of the current method
1557           sp...........current stack pointer
1558
1559    RETURN VALUE:
1560       the address of the first matching exception handler, or
1561           NULL if no handler was found
1562
1563 *******************************************************************************/
1564
1565 #if defined(ENABLE_JIT)
1566 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1567 {
1568         methodinfo            *m;
1569         codeinfo              *code;
1570         s4                     issync;
1571         dseg_exception_entry  *ex;
1572         s4                     exceptiontablelength;
1573         s4                     i;
1574         classref_or_classinfo  cr;
1575         classinfo             *c;
1576 #if defined(ENABLE_THREADS)
1577         java_objectheader     *o;
1578 #endif
1579
1580         /* get info from the method header */
1581
1582         code                 = *((codeinfo **)            (pv + CodeinfoPointer));
1583         issync               = *((s4 *)                   (pv + IsSync));
1584         ex                   =   (dseg_exception_entry *) (pv + ExTableStart);
1585         exceptiontablelength = *((s4 *)                   (pv + ExTableSize));
1586
1587         /* Get the methodinfo pointer from the codeinfo pointer. For
1588            asm_vm_call_method the codeinfo pointer is NULL. */
1589
1590         m = (code == NULL) ? NULL : code->m;
1591
1592 #if !defined(NDEBUG)
1593         /* print exception trace */
1594
1595         if (opt_verbose || opt_verbosecall || opt_verboseexception)
1596                 builtin_trace_exception(xptr, m, xpc, 1);
1597 #endif
1598
1599         for (i = 0; i < exceptiontablelength; i++) {
1600                 /* ATTENTION: keep this here, as we need to decrement the
1601            pointer before the loop executes! */
1602
1603                 ex--;
1604
1605                 /* If the start and end PC is NULL, this means we have the
1606                    special case of asm_vm_call_method.  So, just return the
1607                    proper exception handler. */
1608
1609                 if ((ex->startpc == NULL) && (ex->endpc == NULL))
1610                         return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
1611
1612                 /* is the xpc is the current catch range */
1613
1614                 if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
1615                         cr = ex->catchtype;
1616
1617                         /* NULL catches everything */
1618
1619                         if (cr.any == NULL) {
1620 #if !defined(NDEBUG)
1621                                 /* Print stacktrace of exception when caught. */
1622
1623                                 if (opt_verboseexception) {
1624                                         exceptions_print_exception(xptr);
1625                                         stacktrace_print_trace(xptr);
1626                                 }
1627 #endif
1628
1629                                 return ex->handlerpc;
1630                         }
1631
1632                         /* resolve or load/link the exception class */
1633
1634                         if (IS_CLASSREF(cr)) {
1635                                 /* The exception class reference is unresolved. */
1636                                 /* We have to do _eager_ resolving here. While the class of */
1637                                 /* the exception object is guaranteed to be loaded, it may  */
1638                                 /* well have been loaded by a different loader than the     */
1639                                 /* defining loader of m's class, which is the one we must   */
1640                                 /* use to resolve the catch class. Thus lazy resolving      */
1641                                 /* might fail, even if the result of the resolution would   */
1642                                 /* be an already loaded class.                              */
1643
1644                                 c = resolve_classref_eager(cr.ref);
1645
1646                                 if (c == NULL) {
1647                                         /* Exception resolving the exception class, argh! */
1648                                         return NULL;
1649                                 }
1650
1651                                 /* Ok, we resolved it. Enter it in the table, so we don't */
1652                                 /* have to do this again.                                 */
1653                                 /* XXX this write should be atomic. Is it?                */
1654
1655                                 ex->catchtype.cls = c;
1656                         } else {
1657                                 c = cr.cls;
1658
1659                                 /* XXX I don't think this case can ever happen. -Edwin */
1660                                 if (!(c->state & CLASS_LOADED))
1661                                         /* use the methods' classloader */
1662                                         if (!load_class_from_classloader(c->name,
1663                                                                                                          m->class->classloader))
1664                                                 return NULL;
1665
1666                                 /* XXX I think, if it is not linked, we can be sure that     */
1667                                 /* the exception object is no (indirect) instance of it, no? */
1668                                 /* -Edwin                                                    */
1669                                 if (!(c->state & CLASS_LINKED))
1670                                         if (!link_class(c))
1671                                                 return NULL;
1672                         }
1673
1674                         /* is the thrown exception an instance of the catch class? */
1675
1676                         if (builtin_instanceof(xptr, c)) {
1677 #if !defined(NDEBUG)
1678                                 /* Print stacktrace of exception when caught. */
1679
1680                                 if (opt_verboseexception) {
1681                                         exceptions_print_exception(xptr);
1682                                         stacktrace_print_trace(xptr);
1683                                 }
1684 #endif
1685
1686                                 return ex->handlerpc;
1687                         }
1688                 }
1689         }
1690
1691 #if defined(ENABLE_THREADS)
1692         /* is this method synchronized? */
1693
1694         if (issync) {
1695                 /* get synchronization object */
1696
1697 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1698                 /* XXX change this if we ever want to use 4-byte stackslots */
1699                 o = *((java_objectheader **) (sp + issync - 8));
1700 # else
1701                 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1702 #endif
1703
1704                 assert(o != NULL);
1705
1706                 lock_monitor_exit(o);
1707         }
1708 #endif
1709
1710         /* none of the exceptions catch this one */
1711
1712         return NULL;
1713 }
1714 #endif /* defined(ENABLE_JIT) */
1715
1716
1717 /* exceptions_print_exception **************************************************
1718
1719    Prints an exception, the detail message and the cause, if
1720    available, with CACAO internal functions to stdout.
1721
1722 *******************************************************************************/
1723
1724 void exceptions_print_exception(java_objectheader *xptr)
1725 {
1726         java_lang_Throwable   *t;
1727 #if defined(ENABLE_JAVASE)
1728         java_lang_Throwable   *cause;
1729 #endif
1730         utf                   *u;
1731
1732         t = (java_lang_Throwable *) xptr;
1733
1734         if (t == NULL) {
1735                 puts("NULL\n");
1736                 return;
1737         }
1738
1739 #if defined(ENABLE_JAVASE)
1740         cause = t->cause;
1741 #endif
1742
1743         /* print the root exception */
1744
1745         utf_display_printable_ascii_classname(t->header.vftbl->class->name);
1746
1747         if (t->detailMessage != NULL) {
1748                 u = javastring_toutf(t->detailMessage, false);
1749
1750                 printf(": ");
1751                 utf_display_printable_ascii(u);
1752         }
1753
1754         putc('\n', stdout);
1755
1756 #if defined(ENABLE_JAVASE)
1757         /* print the cause if available */
1758
1759         if ((cause != NULL) && (cause != t)) {
1760                 printf("Caused by: ");
1761                 utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
1762
1763                 if (cause->detailMessage) {
1764                         u = javastring_toutf(cause->detailMessage, false);
1765
1766                         printf(": ");
1767                         utf_display_printable_ascii(u);
1768                 }
1769
1770                 putc('\n', stdout);
1771         }
1772 #endif
1773 }
1774
1775
1776 /*
1777  * These are local overrides for various environment variables in Emacs.
1778  * Please do not remove this and leave it at the end of the file, where
1779  * Emacs will automagically detect them.
1780  * ---------------------------------------------------------------------
1781  * Local variables:
1782  * mode: c
1783  * indent-tabs-mode: t
1784  * c-basic-offset: 4
1785  * tab-width: 4
1786  * End:
1787  * vim:noexpandtab:sw=4:ts=4:
1788  */