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