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