Initial revision
[cacao.git] / builtin.c
1 /* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
2 /****************************** builtin.c **************************************
3
4         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5
6         See file COPYRIGHT for information on usage and disclaimer of warranties
7
8         Enthaelt die C-Funktionen fuer alle JavaVM-Befehle, die sich nicht direkt
9         auf Maschinencode "ubersetzen lassen. Im Code f"ur die Methoden steht
10         dann ein Funktionsaufruf (nat"urlich mit den Aufrufskonventionen von C).
11
12         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
13                  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
14                  Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
15
16         Last Change: 1996/12/03
17
18 *******************************************************************************/
19
20 #include <assert.h>
21 #include <values.h>
22
23 #include "global.h"
24 #include "builtin.h"
25
26 #include "loader.h"
27 #include "tables.h"
28
29 #include "threads/thread.h"
30 #include "threads/locks.h"              /* schani */
31
32 #include "sysdep/native-math.h"
33
34 builtin_descriptor builtin_desc[] = {
35         {(functionptr) builtin_instanceof,         "instanceof"},
36         {(functionptr) builtin_checkcast,          "checkcast"},
37         {(functionptr) new_builtin_checkcast,      "checkcast"},
38         {(functionptr) builtin_arrayinstanceof,    "arrayinstanceof"},
39         {(functionptr) builtin_checkarraycast,     "checkarraycast"},
40         {(functionptr) new_builtin_checkarraycast, "checkarraycast"},
41         {(functionptr) new_builtin_aastore,        "aastore"},
42         {(functionptr) builtin_new,                "new"},
43         {(functionptr) builtin_anewarray,          "anewarray"},
44         {(functionptr) builtin_newarray_array,     "newarray_array"},
45         {(functionptr) builtin_newarray_boolean,   "newarray_boolean"},
46         {(functionptr) builtin_newarray_char,      "newarray_char"},
47         {(functionptr) builtin_newarray_float,     "newarray_float"},
48         {(functionptr) builtin_newarray_double,    "newarray_double"},
49         {(functionptr) builtin_newarray_byte,      "newarray_byte"},
50         {(functionptr) builtin_newarray_short,     "newarray_short"},
51         {(functionptr) builtin_newarray_int,       "newarray_int"},
52         {(functionptr) builtin_newarray_long,      "newarray_long"},
53         {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
54         {(functionptr) builtin_displaymethodstop,  "displaymethodstop"},
55         {(functionptr) builtin_monitorenter,       "monitorenter"},
56         {(functionptr) new_builtin_monitorenter,   "monitorenter"},
57         {(functionptr) builtin_monitorexit,        "monitorexit"},
58         {(functionptr) new_builtin_monitorexit,    "monitorexit"},
59         {(functionptr) builtin_idiv,               "idiv"},
60         {(functionptr) new_builtin_idiv,           "idiv"},
61         {(functionptr) builtin_irem,               "irem"},
62         {(functionptr) new_builtin_irem,           "irem"},
63         {(functionptr) builtin_ladd,               "ladd"},
64         {(functionptr) builtin_lsub,               "lsub"},
65         {(functionptr) builtin_lmul,               "lmul"},
66         {(functionptr) builtin_ldiv,               "ldiv"},
67         {(functionptr) new_builtin_ldiv,           "ldiv"},
68         {(functionptr) builtin_lrem,               "lrem"},
69         {(functionptr) new_builtin_lrem,           "lrem"},
70         {(functionptr) builtin_lshl,               "lshl"},
71         {(functionptr) builtin_lshr,               "lshr"},
72         {(functionptr) builtin_lushr,              "lushr"},
73         {(functionptr) builtin_land,               "land"},
74         {(functionptr) builtin_lor,                "lor"},
75         {(functionptr) builtin_lxor,               "lxor"},
76         {(functionptr) builtin_lneg,               "lneg"},
77         {(functionptr) builtin_lcmp,               "lcmp"},
78         {(functionptr) builtin_fadd,               "fadd"},
79         {(functionptr) builtin_fsub,               "fsub"},
80         {(functionptr) builtin_fmul,               "fmul"},
81         {(functionptr) builtin_fdiv,               "fdiv"},
82         {(functionptr) builtin_frem,               "frem"},
83         {(functionptr) builtin_fneg,               "fneg"},
84         {(functionptr) builtin_fcmpl,              "fcmpl"},
85         {(functionptr) builtin_fcmpg,              "fcmpg"},
86         {(functionptr) builtin_dadd,               "dadd"},
87         {(functionptr) builtin_dsub,               "dsub"},
88         {(functionptr) builtin_dmul,               "dmul"},
89         {(functionptr) builtin_ddiv,               "ddiv"},
90         {(functionptr) builtin_drem,               "drem"},
91         {(functionptr) builtin_dneg,               "dneg"},
92         {(functionptr) builtin_dcmpl,              "dcmpl"},
93         {(functionptr) builtin_dcmpg,              "dcmpg"},
94         {(functionptr) builtin_i2l,                "i2l"},
95         {(functionptr) builtin_i2f,                "i2f"},
96         {(functionptr) builtin_i2d,                "i2d"},
97         {(functionptr) builtin_l2i,                "l2i"},
98         {(functionptr) builtin_l2f,                "l2f"},
99         {(functionptr) builtin_l2d,                "l2d"},
100         {(functionptr) builtin_f2i,                "f2i"},
101         {(functionptr) builtin_f2l,                "f2l"},
102         {(functionptr) builtin_f2d,                "f2d"},
103         {(functionptr) builtin_d2i,                "d2i"},
104         {(functionptr) builtin_d2l,                "d2l"},
105         {(functionptr) builtin_d2f,                "d2f"},
106         {(functionptr) NULL,                       "unknown"}
107         };
108
109
110 /*****************************************************************************
111                                 TYPCHECKS
112 *****************************************************************************/
113
114
115
116 /*************** interne Funktion: builtin_isanysubclass *********************
117
118         "uberpr"uft, ob eine Klasse eine Unterklasse einer anderen Klasse ist.
119         Dabei gelten auch Interfaces, die eine Klasse implementiert, als
120         deren Oberklassen. 
121         R"uckgabewert:  1 ... es trifft zu
122                         0 ... es trifft nicht zu
123                         
124 *****************************************************************************/                  
125
126 static s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
127 {
128         if (super->flags & ACC_INTERFACE) {
129                 u4 index = super->index;
130 /*              if (sub->vftbl == NULL) return 0; */
131                 if (index >= sub->vftbl->interfacetablelength) return 0;
132                 return ( sub->vftbl->interfacevftbl[index] ) ? 1 : 0;
133                 }
134         else {
135                 while (sub) {
136                         if (sub==super) return 1;
137                         sub = sub->super;
138                         }
139                 return 0;
140                 }
141 }
142
143
144 /****************** Funktion: builtin_instanceof *****************************
145
146         "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
147         abgeleiteten Klasse) ist, oder ob die Klasse des Objekts ein Interface 
148         implementiert.
149         Return:   1, wenn ja
150                   0, wenn nicht, oder wenn Objekt ein NULL-Zeiger
151                  
152 *****************************************************************************/
153
154 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
155 {
156 #ifdef DEBUG
157         log_text ("builtin_instanceof called");
158 #endif
159         
160         if (!obj) return 0;
161         return builtin_isanysubclass (obj->vftbl->class, class);
162 }
163
164
165
166 /**************** Funktion: builtin_checkcast *******************************
167
168         "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
169         abgeleiteten Klasse ist).
170         Unterschied zu builtin_instanceof: Ein NULL-Zeiger ist immer richtig
171         Return:   1, wenn ja, oder wenn Objekt ein NULL-Zeiger 
172               0, wenn nicht
173               
174 ****************************************************************************/
175
176 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
177 {
178 #ifdef DEBUG
179         log_text ("builtin_checkcast called");
180 #endif
181
182         if (!obj) return 1;
183         if ( builtin_isanysubclass (obj->vftbl->class, class) ) {
184                 return 1;
185                                 }
186 #if DEBUG
187                 printf ("#### checkcast failed ");
188                 unicode_display (obj->vftbl->class->name);
189                 printf (" -> ");
190                 unicode_display (class->name);
191                 printf ("\n");
192 #endif
193                 
194         return 0;
195 }
196
197
198
199 /*********** interne Funktion: builtin_descriptorscompatible ******************
200
201         "uberpr"uft, ob zwei Array-Typdescriptoren compartible sind, d.h.,
202         ob ein Array vom Typ 'desc' gefahrlos einer Variblen vom Typ 'target'
203         zugewiesen werden kann.
204         Return: 1, wenn ja
205                 0, wenn nicht
206                 
207 ******************************************************************************/
208
209 static s4 builtin_descriptorscompatible
210         (constant_arraydescriptor *desc, constant_arraydescriptor *target)
211 {
212         if (desc==target) return 1;
213         if (desc->arraytype != target->arraytype) return 0;
214         switch (target->arraytype) {
215                 case ARRAYTYPE_OBJECT: 
216                         return builtin_isanysubclass (desc->objectclass, target->objectclass);
217                 case ARRAYTYPE_ARRAY:
218                         return builtin_descriptorscompatible 
219                           (desc->elementdescriptor, target->elementdescriptor);
220                 default: return 1;
221                 }
222 }
223
224
225
226 /******************** Funktion: builtin_checkarraycast ***********************
227
228         "uberpr"uft, ob ein gegebenes Objekt tats"achlich von einem 
229         Untertyp des geforderten Arraytyps ist.
230         Dazu muss das Objekt auf jeden Fall ein Array sein. 
231         Bei einfachen Arrays (int,short,double,etc.) muss der Typ genau 
232         "ubereinstimmen.
233         Bei Arrays von Objekten muss der Elementtyp des tats"achlichen Arrays
234         ein Untertyp (oder der selbe Typ) vom geforderten Elementtyp sein.
235         Bei Arrays vom Arrays (die eventuell wieder Arrays von Arrays
236         sein k"onnen) m"ussen die untersten Elementtypen in der entsprechenden
237         Unterklassenrelation stehen.
238
239         Return: 1, wenn Cast in Ordung ist
240                         0, wenn es nicht geht
241         
242         Achtung: ein Cast mit einem NULL-Zeiger geht immer gut.
243                         
244 *****************************************************************************/
245
246 s4 builtin_checkarraycast(java_objectheader *o, constant_arraydescriptor *desc)
247 {
248         java_arrayheader *a = (java_arrayheader*) o;
249
250         if (!o) return 1;
251         if (o->vftbl->class != class_array) {
252                 return 0;
253                 }
254                 
255         if (a->arraytype != desc->arraytype) {
256                 return 0;
257                 }
258         
259         switch (a->arraytype) {
260                 case ARRAYTYPE_OBJECT: {
261                         java_objectarray *oa = (java_objectarray*) o;
262                         return builtin_isanysubclass (oa->elementtype, desc->objectclass);
263                         }
264                 case ARRAYTYPE_ARRAY: {
265                         java_arrayarray *aa = (java_arrayarray*) o;
266                         return builtin_descriptorscompatible
267                            (aa->elementdescriptor, desc->elementdescriptor);
268                         }
269                 default:   
270                         return 1;
271                 }
272 }
273
274
275 s4 builtin_arrayinstanceof
276         (java_objectheader *obj, constant_arraydescriptor *desc)
277 {
278         if (!obj) return 1;
279         return builtin_checkarraycast (obj, desc);
280 }
281
282
283 /************************** exception functions *******************************
284
285 ******************************************************************************/
286
287 java_objectheader *builtin_throw_exception (java_objectheader *exceptionptr) {
288         unicode_display (exceptionptr->vftbl->class->name);
289         printf ("\n");
290         fflush (stdout);
291         return exceptionptr;
292 }
293
294
295 /******************* Funktion: builtin_canstore *******************************
296
297         "uberpr"uft, ob ein Objekt in einem Array gespeichert werden 
298         darf.
299         Return: 1, wenn es geht
300                         0, wenn nicht
301
302 ******************************************************************************/
303
304
305 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
306 {
307         if (!o) return 1;
308         
309         switch (a->header.arraytype) {
310         case ARRAYTYPE_OBJECT:
311                 if ( ! builtin_checkcast (o, a->elementtype) ) {
312                         return 0;
313                         }
314                 return 1;
315                 break;
316
317         case ARRAYTYPE_ARRAY:
318                 if ( ! builtin_checkarraycast 
319                          (o, ((java_arrayarray*)a)->elementdescriptor) ) {
320                         return 0;
321                         }
322                 return 1;
323                 break;
324
325         default:
326                 panic ("builtin_canstore called with invalid arraytype");
327                 return 0;
328         }
329 }
330
331
332
333 /*****************************************************************************
334                           ARRAYOPERATIONEN
335 *****************************************************************************/
336
337
338
339 /******************** Funktion: builtin_new **********************************
340
341         Legt ein neues Objekt einer Klasse am Heap an.
342         Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
343                         mehr frei ist.
344                         
345 *****************************************************************************/
346
347 java_objectheader *builtin_new (classinfo *c)
348 {
349         java_objectheader *o;
350         
351         o = heap_allocate ( c->instancesize, true, c->finalizer );
352         if (!o) return NULL;
353         
354         memset (o, 0, c->instancesize);
355
356         o -> vftbl = c -> vftbl;
357         return o;
358 }
359
360
361
362 /******************** Funktion: builtin_anewarray ****************************
363
364         Legt ein Array von Zeigern auf Objekte am Heap an.
365         Parameter: 
366                 size ......... Anzahl der Elemente
367                 elementtype .. ein Zeiger auf die classinfo-Struktur des Typs
368                                der Elemente
369
370         Return: Zeiger auf das Array, oder NULL (wenn kein Speicher frei)
371
372 *****************************************************************************/
373
374 java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype)
375 {
376         s4 i;
377         java_objectarray *a;
378         
379         a = heap_allocate ( sizeof(java_objectarray) + (size-1) * sizeof(void*), 
380                             true, 0 /* FALSE */ );
381         if (!a) return NULL;
382         
383         a -> header.objheader.vftbl = class_array -> vftbl;
384         a -> header.size = size;
385         a -> header.arraytype = ARRAYTYPE_OBJECT;
386         a -> elementtype = elementtype;
387         for (i=0; i<size; i++) a->data[i] = NULL;
388         return a;
389 }
390
391
392
393 /******************** Funktion: builtin_newarray_array ***********************
394
395         Legt ein Array von Zeigern auf Arrays am Heap an.
396         Paramter: size ......... Anzahl der Elemente
397                   elementdesc .. Zeiger auf die Arraybeschreibungs-Struktur f"ur
398                                  die Element-Arrays.
399
400         Return: Zeiger auf das Array, oder NULL
401
402 *****************************************************************************/
403
404 java_arrayarray *builtin_newarray_array 
405         (s4 size, constant_arraydescriptor *elementdesc)
406 {
407         s4 i;
408         java_arrayarray *a;
409         
410         a = heap_allocate ( sizeof(java_arrayarray) + (size-1) * sizeof(void*), 
411                             true, NULL );
412         if (!a) return NULL;
413         
414         a -> header.objheader.vftbl = class_array -> vftbl;
415         a -> header.size = size;
416         a -> header.arraytype = ARRAYTYPE_ARRAY;
417         a -> elementdescriptor = elementdesc;
418         for (i=0; i<size; i++) a->data[i] = NULL;
419         return a;
420 }
421
422
423 /******************** Funktion: builtin_newarray_boolean ************************
424
425         Legt ein Array von Bytes am Heap an, das allerdings als Boolean-Array 
426         gekennzeichnet wird (wichtig bei Casts!)
427
428         Return: Zeiger auf das Array, oder NULL 
429
430 *****************************************************************************/
431
432 java_booleanarray *builtin_newarray_boolean (s4 size)
433 {
434         java_booleanarray *a;
435         
436         a = heap_allocate ( sizeof(java_booleanarray) + (size-1) * sizeof(u1), 
437                             false, NULL );
438         if (!a) return NULL;
439         
440         a -> header.objheader.vftbl = class_array -> vftbl;
441         a -> header.size = size;
442         a -> header.arraytype = ARRAYTYPE_BOOLEAN;
443         memset (a->data, 0, sizeof(u1) * size);
444
445         return a;
446 }
447
448 /******************** Funktion: builtin_newarray_char ************************
449
450         Legt ein Array von 16-bit-Integers am Heap an.
451         Return: Zeiger auf das Array, oder NULL 
452
453 *****************************************************************************/
454
455 java_chararray *builtin_newarray_char (s4 size)
456 {
457         java_chararray *a;
458         
459         a = heap_allocate ( sizeof(java_chararray) + (size-1) * sizeof(u2), 
460                             false, NULL );
461         if (!a) return NULL;
462         
463         a -> header.objheader.vftbl = class_array -> vftbl;
464         a -> header.size = size;
465         a -> header.arraytype = ARRAYTYPE_CHAR;
466         memset (a->data, 0, sizeof(u2) * size);
467
468         return a;
469 }
470
471
472 /******************** Funktion: builtin_newarray_float ***********************
473
474         Legt ein Array von 32-bit-IEEE-float am Heap an.
475         Return: Zeiger auf das Array, oder NULL 
476
477 *****************************************************************************/
478
479 java_floatarray *builtin_newarray_float (s4 size)
480 {
481         s4 i;
482         java_floatarray *a;
483         
484         a = heap_allocate ( sizeof(java_floatarray) + (size-1) * sizeof(float), 
485                             false, NULL );
486         if (!a) return NULL;
487
488         a -> header.objheader.vftbl = class_array -> vftbl;
489         a -> header.size = size;
490         a -> header.arraytype = ARRAYTYPE_FLOAT;
491         for (i=0; i<size; i++) a->data[i] = 0.0;
492         return a;
493 }
494
495
496 /******************** Funktion: builtin_newarray_double ***********************
497
498         Legt ein Array von 64-bit-IEEE-float am Heap an.
499         Return: Zeiger auf das Array, oder NULL 
500
501 *****************************************************************************/
502
503 java_doublearray *builtin_newarray_double (s4 size)
504 {
505         s4 i;
506         java_doublearray *a;
507         
508         a = heap_allocate ( sizeof(java_doublearray) + (size-1) * sizeof(double), 
509                             false, NULL );
510         if (!a) return NULL;
511         
512         a -> header.objheader.vftbl = class_array -> vftbl;
513         a -> header.size = size;
514         a -> header.arraytype = ARRAYTYPE_DOUBLE;
515         for (i=0; i<size; i++) a->data[i] = 0.0;
516         return a;
517 }
518
519
520
521
522 /******************** Funktion: builtin_newarray_byte ***********************
523
524         Legt ein Array von 8-bit-Integers am Heap an.
525         Return: Zeiger auf das Array, oder NULL 
526
527 *****************************************************************************/
528
529 java_bytearray *builtin_newarray_byte (s4 size)
530 {
531         java_bytearray *a;
532         
533         a = heap_allocate ( sizeof(java_bytearray) + (size-1) * sizeof(s1), 
534                             false, NULL );
535         if (!a) return NULL;
536         
537         a -> header.objheader.vftbl = class_array->vftbl;
538         a -> header.size = size;
539         a -> header.arraytype = ARRAYTYPE_BYTE;
540         memset (a->data, 0, sizeof(u1) * size);
541         return a;
542 }
543
544
545 /******************** Funktion: builtin_newarray_short ***********************
546
547         Legt ein Array von 16-bit-Integers am Heap an.
548         Return: Zeiger auf das Array, oder NULL 
549
550 *****************************************************************************/
551
552 java_shortarray *builtin_newarray_short (s4 size)
553 {
554         java_shortarray *a;
555         
556         a = heap_allocate ( sizeof(java_shortarray) + (size-1) * sizeof(s2), 
557                             false, NULL );
558         if (!a) return NULL;
559         
560         a -> header.objheader.vftbl = class_array -> vftbl;
561         a -> header.size = size;
562         a -> header.arraytype = ARRAYTYPE_SHORT;
563         memset (a->data, 0, sizeof(s2) * size);
564         return a;
565 }
566
567
568 /******************** Funktion: builtin_newarray_int ***********************
569
570         Legt ein Array von 32-bit-Integers am Heap an.
571         Return: Zeiger auf das Array, oder NULL 
572
573 *****************************************************************************/
574
575 java_intarray *builtin_newarray_int (s4 size)
576 {
577         java_intarray *a;
578         
579         a = heap_allocate ( sizeof(java_intarray) + (size-1) * sizeof(s4), 
580                             false, NULL );
581         if (!a) return NULL;
582         
583         a -> header.objheader.vftbl = class_array -> vftbl;
584         a -> header.size = size;
585         a -> header.arraytype = ARRAYTYPE_INT;
586         memset (a->data, 0, sizeof(s4) * size);
587         return a;
588 }
589
590
591 /******************** Funktion: builtin_newarray_long ***********************
592
593         Legt ein Array von 64-bit-Integers am Heap an.
594         Return: Zeiger auf das Array, oder NULL 
595
596 *****************************************************************************/
597
598 java_longarray *builtin_newarray_long (s4 size)
599 {
600         java_longarray *a;
601         
602         a = heap_allocate ( sizeof(java_longarray) + (size-1) * sizeof(s8), 
603                             false, NULL );
604         if (!a) return NULL;
605
606         a -> header.objheader.vftbl = class_array -> vftbl;
607         a -> header.size = size;
608         a -> header.arraytype = ARRAYTYPE_LONG;
609         memset (a->data, 0, sizeof(s8) * size);
610         return a;
611 }
612
613
614
615 /***************** Funktion: builtin_multianewarray ***************************
616
617         Legt ein mehrdimensionales Array am Heap an.
618         Die Gr"ossen der einzelnen Dimensionen werden in einem Integerarray
619         "ubergeben. Der Typ es zu erzeugenden Arrays wird als 
620         Referenz auf eine constant_arraydescriptor - Struktur "ubergeben.
621
622         Return: Ein Zeiger auf das Array, oder NULL, wenn kein Speicher mehr
623                 vorhanden ist.
624
625 ******************************************************************************/
626
627         /* Hilfsfunktion */
628
629 static java_arrayheader *multianewarray_part (java_intarray *dims, int thisdim,
630                        constant_arraydescriptor *desc)
631 {
632         u4 size,i;
633         java_arrayarray *a;
634
635         size = dims -> data[thisdim];
636         
637         if (thisdim == (dims->header.size-1)) {
638                 /* letzte Dimension schon erreicht */
639                 
640                 switch (desc -> arraytype) {
641                 case ARRAYTYPE_BOOLEAN:  
642                         return (java_arrayheader*) builtin_newarray_boolean (size); 
643                 case ARRAYTYPE_CHAR:  
644                         return (java_arrayheader*) builtin_newarray_char (size); 
645                 case ARRAYTYPE_FLOAT:  
646                         return (java_arrayheader*) builtin_newarray_float (size); 
647                 case ARRAYTYPE_DOUBLE:  
648                         return (java_arrayheader*) builtin_newarray_double (size); 
649                 case ARRAYTYPE_BYTE:  
650                         return (java_arrayheader*) builtin_newarray_byte (size); 
651                 case ARRAYTYPE_SHORT:  
652                         return (java_arrayheader*) builtin_newarray_short (size); 
653                 case ARRAYTYPE_INT:  
654                         return (java_arrayheader*) builtin_newarray_int (size); 
655                 case ARRAYTYPE_LONG:  
656                         return (java_arrayheader*) builtin_newarray_long (size); 
657                 case ARRAYTYPE_OBJECT:
658                         return (java_arrayheader*) builtin_anewarray (size, desc->objectclass);
659                 
660                 case ARRAYTYPE_ARRAY:
661                         return (java_arrayheader*) builtin_newarray_array (size, desc->elementdescriptor);
662                 
663                 default: panic ("Invalid arraytype in multianewarray");
664                 }
665                 }
666
667         /* wenn letzte Dimension noch nicht erreicht wurde */
668
669         if (desc->arraytype != ARRAYTYPE_ARRAY) 
670                 panic ("multianewarray with too many dimensions");
671
672         a = builtin_newarray_array (size, desc->elementdescriptor);
673         if (!a) return NULL;
674         
675         for (i=0; i<size; i++) {
676                 java_arrayheader *ea = 
677                   multianewarray_part (dims, thisdim+1, desc->elementdescriptor);
678                 if (!ea) return NULL;
679
680                 a -> data[i] = ea;
681                 }
682                 
683         return (java_arrayheader*) a;
684 }
685
686
687 java_arrayheader *builtin_multianewarray (java_intarray *dims,
688                       constant_arraydescriptor *desc)
689 {
690         return multianewarray_part (dims, 0, desc);
691 }
692
693
694 static java_arrayheader *nmultianewarray_part (int n, long *dims, int thisdim,
695                        constant_arraydescriptor *desc)
696 {
697         int size, i;
698         java_arrayarray *a;
699
700         size = (int) dims[thisdim];
701         
702         if (thisdim == (n - 1)) {
703                 /* letzte Dimension schon erreicht */
704                 
705                 switch (desc -> arraytype) {
706                 case ARRAYTYPE_BOOLEAN:  
707                         return (java_arrayheader*) builtin_newarray_boolean(size); 
708                 case ARRAYTYPE_CHAR:  
709                         return (java_arrayheader*) builtin_newarray_char(size); 
710                 case ARRAYTYPE_FLOAT:  
711                         return (java_arrayheader*) builtin_newarray_float(size); 
712                 case ARRAYTYPE_DOUBLE:  
713                         return (java_arrayheader*) builtin_newarray_double(size); 
714                 case ARRAYTYPE_BYTE:  
715                         return (java_arrayheader*) builtin_newarray_byte(size); 
716                 case ARRAYTYPE_SHORT:  
717                         return (java_arrayheader*) builtin_newarray_short(size); 
718                 case ARRAYTYPE_INT:  
719                         return (java_arrayheader*) builtin_newarray_int(size); 
720                 case ARRAYTYPE_LONG:  
721                         return (java_arrayheader*) builtin_newarray_long(size); 
722                 case ARRAYTYPE_OBJECT:
723                         return (java_arrayheader*) builtin_anewarray(size,
724                                                    desc->objectclass);
725                 case ARRAYTYPE_ARRAY:
726                         return (java_arrayheader*) builtin_newarray_array(size,
727                                                    desc->elementdescriptor);
728                 
729                 default: panic ("Invalid arraytype in multianewarray");
730                 }
731                 }
732
733         /* wenn letzte Dimension noch nicht erreicht wurde */
734
735         if (desc->arraytype != ARRAYTYPE_ARRAY) 
736                 panic ("multianewarray with too many dimensions");
737
738         a = builtin_newarray_array(size, desc->elementdescriptor);
739         if (!a) return NULL;
740         
741         for (i = 0; i < size; i++) {
742                 java_arrayheader *ea = 
743                         nmultianewarray_part(n, dims, thisdim + 1, desc->elementdescriptor);
744                 if (!ea) return NULL;
745
746                 a -> data[i] = ea;
747                 }
748                 
749         return (java_arrayheader*) a;
750 }
751
752
753 java_arrayheader *builtin_nmultianewarray (int size,
754                       constant_arraydescriptor *desc, long *dims)
755 {
756         (void) builtin_newarray_int(size); /* for compatibility with -old */
757         return nmultianewarray_part (size, dims, 0, desc);
758 }
759
760
761
762
763 /************************* Funktion: builtin_aastore *************************
764
765         speichert eine Referenz auf ein Objekt in einem Object-Array oder
766         in einem Array-Array.
767         Dabei wird allerdings vorher "uberpr"uft, ob diese Operation 
768         zul"assig ist.
769
770         Return: 1, wenn alles OK ist
771                 0, wenn dieses Objekt nicht in dieses Array gespeichert werden
772                    darf
773
774 *****************************************************************************/
775
776 s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o)
777 {
778         if (builtin_canstore(a,o)) {
779                 a->data[index] = o;
780                 return 1;
781                 }
782         return 0;
783 }
784
785
786
787
788
789
790 /*****************************************************************************
791                       METHODEN-PROTOKOLLIERUNG
792
793         Verschiedene Funktionen, mit denen eine Meldung ausgegeben werden
794         kann, wann immer Methoden aufgerufen oder beendet werden.
795         (f"ur Debug-Zwecke)
796
797 *****************************************************************************/
798
799
800 u4 methodindent=0;
801
802 java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
803                    methodinfo *method, int *pos, int noindent) {
804
805         if (!noindent)
806                 methodindent--;
807         if (verbose || runverbose) {
808                 printf("Exception ");
809                 unicode_display (exceptionptr->vftbl->class->name);
810                 printf(" thrown in ");
811                 if (method) {
812                         unicode_display (method->class->name);
813                         printf(".");
814                         unicode_display (method->name);
815                         if (method->flags & ACC_SYNCHRONIZED)
816                                 printf("(SYNC)");
817                         else
818                                 printf("(NOSYNC)");
819                         printf("(%p) at position %p\n", method->entrypoint, pos);
820                         }
821                 else
822                         printf("call_java_method\n");
823                 fflush (stdout);
824                 }
825         return exceptionptr;
826 }
827
828
829 void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5,
830                         methodinfo *method)
831 {
832         sprintf (logtext, "                                             ");
833         sprintf (logtext+methodindent, "called: ");
834         unicode_sprint (logtext+strlen(logtext), method->class->name);
835         sprintf (logtext+strlen(logtext), ".");
836         unicode_sprint (logtext+strlen(logtext), method->name);
837         unicode_sprint (logtext+strlen(logtext), method->descriptor);
838         sprintf (logtext+strlen(logtext), "(");
839         switch (method->paramcount) {
840                 case 6:
841                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
842                                                    a0,  a1,  a2,  a3,  a4,  a5);
843                         break;
844                 case 5:
845                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
846                                                    a0,  a1,  a2,  a3,  a4);
847                         break;
848                 case 4:
849                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
850                                                    a0,  a1,  a2,  a3);
851                         break;
852                 case 3:
853                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0,  a1,  a2);
854                         break;
855                 case 2:
856                         sprintf(logtext+strlen(logtext), "%lx, %lx", a0,  a1);
857                         break;
858                 case 1:
859                         sprintf(logtext+strlen(logtext), "%lx", a0);
860                         break;
861                 }
862         sprintf (logtext+strlen(logtext), ")");
863
864         dolog ();
865         methodindent++;
866 }
867
868 void builtin_displaymethodstart(methodinfo *method)
869 {
870         sprintf (logtext, "                                             ");
871         sprintf (logtext+methodindent, "called: ");
872         unicode_sprint (logtext+strlen(logtext), method->class->name);
873         sprintf (logtext+strlen(logtext), ".");
874         unicode_sprint (logtext+strlen(logtext), method->name);
875         unicode_sprint (logtext+strlen(logtext), method->descriptor);
876         dolog ();
877         methodindent++;
878 }
879
880 void builtin_displaymethodstop(methodinfo *method, long l, double d)
881 {
882         methodindent--;
883         sprintf (logtext, "                                             ");
884         sprintf (logtext+methodindent, "finished: ");
885         unicode_sprint (logtext+strlen(logtext), method->class->name);
886         sprintf (logtext+strlen(logtext), ".");
887         unicode_sprint (logtext+strlen(logtext), method->name);
888         unicode_sprint (logtext+strlen(logtext), method->descriptor);
889         switch (method->returntype) {
890                 case TYPE_INT:
891                 case TYPE_LONG:
892                         sprintf (logtext+strlen(logtext), "->%ld", l);
893                         break;
894                 case TYPE_FLOAT:
895                 case TYPE_DOUBLE:
896                         sprintf (logtext+strlen(logtext), "->%g", d);
897                         break;
898                 case TYPE_ADDRESS:
899                         sprintf (logtext+strlen(logtext), "->%p", (void*) l);
900                         break;
901                 }
902         dolog ();
903 }
904
905 void builtin_displaymethodexception(methodinfo *method)
906 {
907         sprintf (logtext, "                                             ");
908         sprintf (logtext+methodindent, "exception abort: ");
909         unicode_sprint (logtext+strlen(logtext), method->class->name);
910         sprintf (logtext+strlen(logtext), ".");
911         unicode_sprint (logtext+strlen(logtext), method->name);
912         unicode_sprint (logtext+strlen(logtext), method->descriptor);
913         dolog ();
914 }
915
916
917 /****************************************************************************
918              SYNCHRONIZATION FUNCTIONS
919 *****************************************************************************/
920
921 /*
922  * Lock the mutex of an object.
923  */
924 #ifdef USE_THREADS
925 void
926 internal_lock_mutex_for_object (java_objectheader *object)
927 {
928     mutexHashEntry *entry;
929     int hashValue;
930
931     assert(object != 0);
932
933     hashValue = MUTEX_HASH_VALUE(object);
934     entry = &mutexHashTable[hashValue];
935
936     if (entry->object != 0)
937     {
938                 if (entry->mutex.count == 0 && entry->conditionCount == 0)
939                 {
940                         entry->object = 0;
941                         entry->mutex.holder = 0;
942                         entry->mutex.count = 0;
943                         entry->mutex.muxWaiters = 0;
944                 }
945         else
946         {
947             while (entry->next != 0 && entry->object != object)
948                 entry = entry->next;
949
950             if (entry->object != object)
951             {
952                         entry->next = firstFreeOverflowEntry;
953                         firstFreeOverflowEntry = firstFreeOverflowEntry->next;
954
955                         entry = entry->next;
956                         entry->object = 0;
957                         entry->next = 0;
958                         assert(entry->conditionCount == 0);
959             }
960         }
961     }
962     else
963     {
964                 entry->mutex.holder = 0;
965                 entry->mutex.count = 0;
966                 entry->mutex.muxWaiters = 0;
967     }
968
969     if (entry->object == 0)
970         entry->object = object;
971     
972     internal_lock_mutex(&entry->mutex);
973 }
974 #endif
975
976
977 /*
978  * Unlocks the mutex of an object.
979  */
980 #ifdef USE_THREADS
981 void
982 internal_unlock_mutex_for_object (java_objectheader *object)
983 {
984     int hashValue;
985     mutexHashEntry *entry;
986
987     hashValue = MUTEX_HASH_VALUE(object);
988     entry = &mutexHashTable[hashValue];
989
990     if (entry->object == object)
991                 internal_unlock_mutex(&entry->mutex);
992     else
993     {
994                 while (entry->next != 0 && entry->next->object != object)
995                         entry = entry->next;
996
997                 assert(entry->next != 0);
998
999                 internal_unlock_mutex(&entry->next->mutex);
1000
1001                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
1002                 {
1003                         mutexHashEntry *unlinked = entry->next;
1004
1005                         entry->next = unlinked->next;
1006                         unlinked->next = firstFreeOverflowEntry;
1007                         firstFreeOverflowEntry = unlinked;
1008                 }
1009     }
1010 }
1011 #endif
1012
1013 void
1014 builtin_monitorenter (java_objectheader *o)
1015 {
1016 #ifdef USE_THREADS
1017     int hashValue;
1018
1019         assert(blockInts == 0);
1020
1021     ++blockInts;
1022
1023     hashValue = MUTEX_HASH_VALUE(o);
1024     if (mutexHashTable[hashValue].object == o
1025                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1026                 ++mutexHashTable[hashValue].mutex.count;
1027     else
1028                 internal_lock_mutex_for_object(o);
1029
1030         --blockInts;
1031
1032         assert(blockInts == 0);
1033 #endif
1034 }
1035
1036 void builtin_monitorexit (java_objectheader *o)
1037 {
1038 #ifdef USE_THREADS
1039     int hashValue;
1040
1041         assert(blockInts == 0);
1042
1043     ++blockInts;
1044
1045     hashValue = MUTEX_HASH_VALUE(o);
1046     if (mutexHashTable[hashValue].object == o)
1047     {
1048                 if (mutexHashTable[hashValue].mutex.count == 1
1049                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1050                         internal_unlock_mutex_for_object(o);
1051                 else
1052                         --mutexHashTable[hashValue].mutex.count;
1053     }
1054     else
1055                 internal_unlock_mutex_for_object(o);
1056
1057         --blockInts;
1058
1059         assert(blockInts == 0);
1060 #endif
1061 }
1062
1063
1064 /*****************************************************************************
1065                       DIVERSE HILFSFUNKTIONEN
1066 *****************************************************************************/
1067
1068
1069
1070 /*********** Funktionen f"ur die Integerdivision *****************************
1071  
1072         Auf manchen Systemen (z.B. DEC ALPHA) wird durch die CPU keine Integer-
1073         division unterst"utzt.
1074         Daf"ur gibt es dann diese Hilfsfunktionen
1075
1076 ******************************************************************************/
1077
1078 s4 builtin_idiv (s4 a, s4 b) { return a/b; }
1079 s4 builtin_irem (s4 a, s4 b) { return a%b; }
1080
1081
1082 /************** Funktionen f"ur Long-Arithmetik *******************************
1083
1084         Auf Systemen, auf denen die CPU keine 64-Bit-Integers unterst"utzt,
1085         werden diese Funktionen gebraucht
1086
1087 ******************************************************************************/
1088
1089
1090 s8 builtin_ladd (s8 a, s8 b) 
1091
1092 #if U8_AVAILABLE
1093         return a+b; 
1094 #else
1095         return builtin_i2l(0);
1096 #endif
1097 }
1098
1099 s8 builtin_lsub (s8 a, s8 b) 
1100
1101 #if U8_AVAILABLE
1102         return a-b; 
1103 #else
1104         return builtin_i2l(0);
1105 #endif
1106 }
1107
1108 s8 builtin_lmul (s8 a, s8 b) 
1109
1110 #if U8_AVAILABLE
1111         return a*b; 
1112 #else
1113         return builtin_i2l(0);
1114 #endif
1115 }
1116
1117 s8 builtin_ldiv (s8 a, s8 b) 
1118
1119 #if U8_AVAILABLE
1120         return a/b; 
1121 #else
1122         return builtin_i2l(0);
1123 #endif
1124 }
1125
1126 s8 builtin_lrem (s8 a, s8 b) 
1127
1128 #if U8_AVAILABLE
1129         return a%b; 
1130 #else
1131         return builtin_i2l(0);
1132 #endif
1133 }
1134
1135 s8 builtin_lshl (s8 a, s4 b) 
1136
1137 #if U8_AVAILABLE
1138         return a<<(b&63);
1139 #else
1140         return builtin_i2l(0);
1141 #endif
1142 }
1143
1144 s8 builtin_lshr (s8 a, s4 b) 
1145
1146 #if U8_AVAILABLE
1147         return a>>(b&63);
1148 #else
1149         return builtin_i2l(0);
1150 #endif
1151 }
1152
1153 s8 builtin_lushr (s8 a, s4 b) 
1154
1155 #if U8_AVAILABLE
1156         return ((u8)a)>>(b&63);
1157 #else
1158         return builtin_i2l(0);
1159 #endif
1160 }
1161
1162 s8 builtin_land (s8 a, s8 b) 
1163
1164 #if U8_AVAILABLE
1165         return a&b; 
1166 #else
1167         return builtin_i2l(0);
1168 #endif
1169 }
1170
1171 s8 builtin_lor (s8 a, s8 b) 
1172
1173 #if U8_AVAILABLE
1174         return a|b; 
1175 #else
1176         return builtin_i2l(0);
1177 #endif
1178 }
1179
1180 s8 builtin_lxor (s8 a, s8 b) 
1181
1182 #if U8_AVAILABLE
1183         return a^b; 
1184 #else
1185         return builtin_i2l(0);
1186 #endif
1187 }
1188
1189 s8 builtin_lneg (s8 a) 
1190
1191 #if U8_AVAILABLE
1192         return -a;
1193 #else
1194         return builtin_i2l(0);
1195 #endif
1196 }
1197
1198 s4 builtin_lcmp (s8 a, s8 b) 
1199
1200 #if U8_AVAILABLE
1201         if (a<b) return -1;
1202         if (a>b) return 1;
1203         return 0;
1204 #else
1205         return 0;
1206 #endif
1207 }
1208
1209
1210
1211
1212
1213 /*********** Funktionen f"ur die Floating-Point-Operationen ******************/
1214
1215 float builtin_fadd (float a, float b)
1216 {
1217         if (isnanf(a)) return FLT_NAN;
1218         if (isnanf(b)) return FLT_NAN;
1219         if (finitef(a)) {
1220                 if (finitef(b)) return a+b;
1221                 else return b;
1222                 }
1223         else {
1224                 if (finitef(b)) return a;
1225                 else {
1226                         if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
1227                         else  return FLT_NAN;
1228                         }
1229                 }
1230 }
1231
1232 float builtin_fsub (float a, float b)
1233 {
1234         return builtin_fadd (a, builtin_fneg(b));
1235 }
1236
1237 float builtin_fmul (float a, float b)
1238 {
1239         if (isnanf(a)) return FLT_NAN;
1240         if (isnanf(b)) return FLT_NAN;
1241         if (finitef(a)) {
1242                 if (finitef(b)) return a*b;
1243                 else {
1244                         if (a==0) return FLT_NAN;
1245                              else return copysignf(b, copysignf(1.0, b)*a);
1246                         }
1247                 }
1248         else {
1249                 if (finitef(b)) {
1250                         if (b==0) return FLT_NAN;
1251                              else return copysignf(a, copysignf(1.0, a)*b);
1252                         }
1253                 else {
1254                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1255                         }
1256                 }
1257 }
1258
1259 float builtin_fdiv (float a, float b)
1260 {
1261         if (finitef(a) && finitef(b)) {
1262                 if (b != 0)
1263                         return a / b;
1264                 else {
1265                         if (a > 0)
1266                                 return FLT_POSINF;
1267                         else if (a < 0)
1268                                 return FLT_NEGINF;
1269                         }
1270                 }
1271         return FLT_NAN;
1272 }
1273
1274 float builtin_frem (float a, float b)
1275 {
1276
1277 /* return (float) builtin_drem((double) a, (double) b); */
1278
1279         float f;
1280
1281         if (finite((double) a) && finite((double) b)) {
1282                 f = a / b;
1283                 if (finite((double) f))
1284                         return fmodf(a, b);
1285                 return FLT_NAN;
1286                 }
1287         if (isnan((double) b))
1288                 return FLT_NAN;
1289         if (finite((double) a))
1290                 return a;
1291         return FLT_NAN;
1292
1293 /*      float f;
1294
1295         if (finitef(a) && finitef(b)) {
1296                 f = a / b;
1297                 if (finitef(f))
1298                         return a - floorf(f) * b;
1299                 return FLT_NAN;
1300                 }
1301         if (isnanf(b))
1302                 return FLT_NAN;
1303         if (finitef(a))
1304                 return a;
1305         return FLT_NAN; */
1306 }
1307
1308
1309 float builtin_fneg (float a)
1310 {
1311         if (isnanf(a)) return a;
1312         else {
1313                 if (finitef(a)) return -a;
1314                            else return copysignf(a,-copysignf(1.0, a));
1315                 }
1316 }
1317
1318 s4 builtin_fcmpl (float a, float b)
1319 {
1320         if (isnanf(a)) return -1;
1321         if (isnanf(b)) return -1;
1322         if (!finitef(a) || !finitef(b)) {
1323                 a = finitef(a) ? 0 : copysignf(1.0,  a);
1324                 b = finitef(b) ? 0 : copysignf(1.0, b);
1325                 }
1326         if (a>b) return 1;
1327         if (a==b) return 0;
1328         return -1;
1329 }
1330
1331 s4 builtin_fcmpg (float a, float b)
1332 {
1333         if (isnanf(a)) return 1;
1334         if (isnanf(b)) return 1;
1335         if (!finitef(a) || !finitef(b)) {
1336                 a = finitef(a) ? 0 : copysignf(1.0, a);
1337                 b = finitef(b) ? 0 : copysignf(1.0, b);
1338                 }
1339         if (a>b) return 1;
1340         if (a==b) return 0;
1341         return -1;
1342 }
1343
1344
1345
1346 /*********** Funktionen f"ur doppelt genaue Fliesskommazahlen ***************/
1347
1348 double builtin_dadd (double a, double b)
1349 {
1350         if (isnan(a)) return DBL_NAN;
1351         if (isnan(b)) return DBL_NAN;
1352         if (finite(a)) {
1353                 if (finite(b)) return a+b;
1354                 else return b;
1355                 }
1356         else {
1357                 if (finite(b)) return a;
1358                 else {
1359                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1360                         else  return DBL_NAN;
1361                         }
1362                 }
1363 }
1364
1365 double builtin_dsub (double a, double b)
1366 {
1367         return builtin_dadd (a, builtin_dneg(b));
1368 }
1369
1370 double builtin_dmul (double a, double b)
1371 {
1372         if (isnan(a)) return DBL_NAN;
1373         if (isnan(b)) return DBL_NAN;
1374         if (finite(a)) {
1375                 if (finite(b)) return a*b;
1376                 else {
1377                         if (a==0) return DBL_NAN;
1378                              else return copysign(b, copysign(1.0, b)*a);
1379                         }
1380                 }
1381         else {
1382                 if (finite(b)) {
1383                         if (b==0) return DBL_NAN;
1384                              else return copysign(a, copysign(1.0, a)*b);
1385                         }
1386                 else {
1387                         return copysign(a, copysign(1.0, a)*copysign(1.0, b));
1388                         }
1389                 }
1390 }
1391
1392 double builtin_ddiv (double a, double b)
1393 {
1394         if (finite(a) && finite(b)) {
1395                 if (b != 0)
1396                         return a / b;
1397                 else {
1398                         if (a > 0)
1399                                 return DBL_POSINF;
1400                         else if (a < 0)
1401                                 return DBL_NEGINF;
1402                         }
1403                 }
1404         return DBL_NAN;
1405 }
1406
1407 double builtin_drem (double a, double b)
1408 {
1409         double d;
1410
1411         if (finite(a) && finite(b)) {
1412                 d = a / b;
1413                 if (finite(d)) {
1414                         if ((d < 1.0) && (d > 0.0))
1415                                 return a;
1416                         return fmod(a, b);
1417                         }
1418                 return DBL_NAN;
1419                 }
1420         if (isnan(b))
1421                 return DBL_NAN;
1422         if (finite(a))
1423                 return a;
1424         return DBL_NAN;
1425 }
1426
1427 double builtin_dneg (double a)
1428 {
1429         if (isnan(a)) return a;
1430         else {
1431                 if (finite(a)) return -a;
1432                           else return copysign(a,-copysign(1.0, a));
1433                 }
1434 }
1435
1436 s4 builtin_dcmpl (double a, double b)
1437 {
1438         if (isnan(a)) return -1;
1439         if (isnan(b)) return -1;
1440         if (!finite(a) || !finite(b)) {
1441                 a = finite(a) ? 0 : copysign(1.0, a);
1442                 b = finite(b) ? 0 : copysign(1.0, b);
1443                 }
1444         if (a>b) return 1;
1445         if (a==b) return 0;
1446         return -1;
1447 }
1448
1449 s4 builtin_dcmpg (double a, double b)
1450 {
1451         if (isnan(a)) return 1;
1452         if (isnan(b)) return 1;
1453         if (!finite(a) || !finite(b)) {
1454                 a = finite(a) ? 0 : copysign(1.0, a);
1455                 b = finite(b) ? 0 : copysign(1.0, b);
1456                 }
1457         if (a>b) return 1;
1458         if (a==b) return 0;
1459         return -1;
1460 }
1461
1462
1463 /*********************** Umwandlungsoperationen ****************************/
1464
1465 s8 builtin_i2l (s4 i)
1466 {
1467 #if U8_AVAILABLE
1468         return i;
1469 #else
1470         s8 v; v.high = 0; v.low=i; return v;
1471 #endif
1472 }
1473
1474 float builtin_i2f (s4 a)
1475 {
1476 float f = (float) a;
1477 return f;
1478 }
1479
1480 double builtin_i2d (s4 a)
1481 {
1482 double d = (double) a;
1483 return d;
1484 }
1485
1486
1487 s4 builtin_l2i (s8 l)
1488 {
1489 #if U8_AVAILABLE
1490         return (s4) l;
1491 #else
1492         return l.low;
1493 #endif
1494 }
1495
1496 float builtin_l2f (s8 a)
1497 {
1498 #if U8_AVAILABLE
1499         float f = (float) a;
1500         return f;
1501 #else
1502         return 0.0;
1503 #endif
1504 }
1505
1506 double builtin_l2d (s8 a)
1507 {
1508 #if U8_AVAILABLE
1509         double d = (double) a;
1510         return d;
1511 #else
1512         return 0.0;
1513 #endif
1514 }
1515
1516
1517 s4 builtin_f2i(float a) 
1518 {
1519
1520 return builtin_d2i((double) a);
1521
1522 /*      float f;
1523         
1524         if (isnanf(a))
1525                 return 0;
1526         if (finitef(a)) {
1527                 if (a > 2147483647)
1528                         return 2147483647;
1529                 if (a < (-2147483648))
1530                         return (-2147483648);
1531                 return (s4) a;
1532                 }
1533         f = copysignf((float) 1.0, a);
1534         if (f > 0)
1535                 return 2147483647;
1536         return (-2147483648); */
1537 }
1538
1539
1540 s8 builtin_f2l (float a)
1541 {
1542
1543 return builtin_d2l((double) a);
1544
1545 /*      float f;
1546         
1547         if (finitef(a)) {
1548                 if (a > 9223372036854775807L)
1549                         return 9223372036854775807L;
1550                 if (a < (-9223372036854775808L))
1551                         return (-9223372036854775808L);
1552                 return (s8) a;
1553                 }
1554         if (isnanf(a))
1555                 return 0;
1556         f = copysignf((float) 1.0, a);
1557         if (f > 0)
1558                 return 9223372036854775807L;
1559         return (-9223372036854775808L); */
1560 }
1561
1562
1563 double builtin_f2d (float a)
1564 {
1565         if (finitef(a)) return (double) a;
1566         else {
1567                 if (isnanf(a)) return DBL_NAN;
1568                 else           return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
1569                 }
1570 }
1571
1572
1573 s4 builtin_d2i (double a) 
1574
1575         double d;
1576         
1577         if (finite(a)) {
1578                 if (a >= 2147483647)
1579                         return 2147483647;
1580                 if (a <= (-2147483648))
1581                         return (-2147483648);
1582                 return (s4) a;
1583                 }
1584         if (isnan(a))
1585                 return 0;
1586         d = copysign(1.0, a);
1587         if (d > 0)
1588                 return 2147483647;
1589         return (-2147483648);
1590 }
1591
1592
1593 s8 builtin_d2l (double a)
1594 {
1595         double d;
1596         
1597         if (finite(a)) {
1598                 if (a >= 9223372036854775807L)
1599                         return 9223372036854775807L;
1600                 if (a <= (-9223372036854775807L-1))
1601                         return (-9223372036854775807L-1);
1602                 return (s8) a;
1603                 }
1604         if (isnan(a))
1605                 return 0;
1606         d = copysign(1.0, a);
1607         if (d > 0)
1608                 return 9223372036854775807L;
1609         return (-9223372036854775807L-1);
1610 }
1611
1612
1613 float builtin_d2f (double a)
1614 {
1615         if (finite(a)) return (float) a;
1616         else {
1617                 if (isnan(a)) return FLT_NAN;
1618                 else          return copysignf (FLT_POSINF, (float) copysign(1.0, a));
1619                 }
1620 }
1621