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