Added Makefile.in (as generated by automake) to narray and doc to allow flawless...
[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                 case TYPE_ADDRESS:
919                         sprintf (logtext+strlen(logtext), "->%ld", l);
920                         break;
921                 case TYPE_FLOAT:
922                 case TYPE_DOUBLE:
923                         sprintf (logtext+strlen(logtext), "->%g", d);
924                         break;
925                 }
926         dolog ();
927 }
928
929 void builtin_displaymethodexception(methodinfo *method)
930 {
931         sprintf (logtext, "                                             ");
932         sprintf (logtext+methodindent, "exception abort: ");
933         utf_sprint (logtext+strlen(logtext), method->class->name);
934         sprintf (logtext+strlen(logtext), ".");
935         utf_sprint (logtext+strlen(logtext), method->name);
936         utf_sprint (logtext+strlen(logtext), method->descriptor);
937         dolog ();
938 }
939
940
941 /****************************************************************************
942              SYNCHRONIZATION FUNCTIONS
943 *****************************************************************************/
944
945 /*
946  * Lock the mutex of an object.
947  */
948 #ifdef USE_THREADS
949 void
950 internal_lock_mutex_for_object (java_objectheader *object)
951 {
952     mutexHashEntry *entry;
953     int hashValue;
954
955     assert(object != 0);
956
957     hashValue = MUTEX_HASH_VALUE(object);
958     entry = &mutexHashTable[hashValue];
959
960     if (entry->object != 0)
961     {
962                 if (entry->mutex.count == 0 && entry->conditionCount == 0)
963                 {
964                         entry->object = 0;
965                         entry->mutex.holder = 0;
966                         entry->mutex.count = 0;
967                         entry->mutex.muxWaiters = 0;
968                 }
969         else
970         {
971             while (entry->next != 0 && entry->object != object)
972                 entry = entry->next;
973
974             if (entry->object != object)
975             {
976                         entry->next = firstFreeOverflowEntry;
977                         firstFreeOverflowEntry = firstFreeOverflowEntry->next;
978
979                         entry = entry->next;
980                         entry->object = 0;
981                         entry->next = 0;
982                         assert(entry->conditionCount == 0);
983             }
984         }
985     }
986     else
987     {
988                 entry->mutex.holder = 0;
989                 entry->mutex.count = 0;
990                 entry->mutex.muxWaiters = 0;
991     }
992
993     if (entry->object == 0)
994         entry->object = object;
995     
996     internal_lock_mutex(&entry->mutex);
997 }
998 #endif
999
1000
1001 /*
1002  * Unlocks the mutex of an object.
1003  */
1004 #ifdef USE_THREADS
1005 void
1006 internal_unlock_mutex_for_object (java_objectheader *object)
1007 {
1008     int hashValue;
1009     mutexHashEntry *entry;
1010
1011     hashValue = MUTEX_HASH_VALUE(object);
1012     entry = &mutexHashTable[hashValue];
1013
1014     if (entry->object == object)
1015                 internal_unlock_mutex(&entry->mutex);
1016     else
1017     {
1018                 while (entry->next != 0 && entry->next->object != object)
1019                         entry = entry->next;
1020
1021                 assert(entry->next != 0);
1022
1023                 internal_unlock_mutex(&entry->next->mutex);
1024
1025                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
1026                 {
1027                         mutexHashEntry *unlinked = entry->next;
1028
1029                         entry->next = unlinked->next;
1030                         unlinked->next = firstFreeOverflowEntry;
1031                         firstFreeOverflowEntry = unlinked;
1032                 }
1033     }
1034 }
1035 #endif
1036
1037 void
1038 builtin_monitorenter (java_objectheader *o)
1039 {
1040 #ifdef USE_THREADS
1041     int hashValue;
1042
1043         assert(blockInts == 0);
1044
1045     ++blockInts;
1046
1047     hashValue = MUTEX_HASH_VALUE(o);
1048     if (mutexHashTable[hashValue].object == o
1049                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1050                 ++mutexHashTable[hashValue].mutex.count;
1051     else
1052                 internal_lock_mutex_for_object(o);
1053
1054         --blockInts;
1055
1056         assert(blockInts == 0);
1057 #endif
1058 }
1059
1060 void builtin_monitorexit (java_objectheader *o)
1061 {
1062 #ifdef USE_THREADS
1063     int hashValue;
1064
1065         assert(blockInts == 0);
1066
1067     ++blockInts;
1068
1069     hashValue = MUTEX_HASH_VALUE(o);
1070     if (mutexHashTable[hashValue].object == o)
1071     {
1072                 if (mutexHashTable[hashValue].mutex.count == 1
1073                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1074                         internal_unlock_mutex_for_object(o);
1075                 else
1076                         --mutexHashTable[hashValue].mutex.count;
1077     }
1078     else
1079                 internal_unlock_mutex_for_object(o);
1080
1081         --blockInts;
1082
1083         assert(blockInts == 0);
1084 #endif
1085 }
1086
1087
1088 /*****************************************************************************
1089                       DIVERSE HILFSFUNKTIONEN
1090 *****************************************************************************/
1091
1092
1093
1094 /*********** Funktionen f"ur die Integerdivision *****************************
1095  
1096         Auf manchen Systemen (z.B. DEC ALPHA) wird durch die CPU keine Integer-
1097         division unterst"utzt.
1098         Daf"ur gibt es dann diese Hilfsfunktionen
1099
1100 ******************************************************************************/
1101
1102 s4 builtin_idiv (s4 a, s4 b) { return a/b; }
1103 s4 builtin_irem (s4 a, s4 b) { return a%b; }
1104
1105
1106 /************** Funktionen f"ur Long-Arithmetik *******************************
1107
1108         Auf Systemen, auf denen die CPU keine 64-Bit-Integers unterst"utzt,
1109         werden diese Funktionen gebraucht
1110
1111 ******************************************************************************/
1112
1113
1114 s8 builtin_ladd (s8 a, s8 b) 
1115
1116 #if U8_AVAILABLE
1117         return a+b; 
1118 #else
1119         return builtin_i2l(0);
1120 #endif
1121 }
1122
1123 s8 builtin_lsub (s8 a, s8 b) 
1124
1125 #if U8_AVAILABLE
1126         return a-b; 
1127 #else
1128         return builtin_i2l(0);
1129 #endif
1130 }
1131
1132 s8 builtin_lmul (s8 a, s8 b) 
1133
1134 #if U8_AVAILABLE
1135         return a*b; 
1136 #else
1137         return builtin_i2l(0);
1138 #endif
1139 }
1140
1141 s8 builtin_ldiv (s8 a, s8 b) 
1142
1143 #if U8_AVAILABLE
1144         return a/b; 
1145 #else
1146         return builtin_i2l(0);
1147 #endif
1148 }
1149
1150 s8 builtin_lrem (s8 a, s8 b) 
1151
1152 #if U8_AVAILABLE
1153         return a%b; 
1154 #else
1155         return builtin_i2l(0);
1156 #endif
1157 }
1158
1159 s8 builtin_lshl (s8 a, s4 b) 
1160
1161 #if U8_AVAILABLE
1162         return a<<(b&63);
1163 #else
1164         return builtin_i2l(0);
1165 #endif
1166 }
1167
1168 s8 builtin_lshr (s8 a, s4 b) 
1169
1170 #if U8_AVAILABLE
1171         return a>>(b&63);
1172 #else
1173         return builtin_i2l(0);
1174 #endif
1175 }
1176
1177 s8 builtin_lushr (s8 a, s4 b) 
1178
1179 #if U8_AVAILABLE
1180         return ((u8)a)>>(b&63);
1181 #else
1182         return builtin_i2l(0);
1183 #endif
1184 }
1185
1186 s8 builtin_land (s8 a, s8 b) 
1187
1188 #if U8_AVAILABLE
1189         return a&b; 
1190 #else
1191         return builtin_i2l(0);
1192 #endif
1193 }
1194
1195 s8 builtin_lor (s8 a, s8 b) 
1196
1197 #if U8_AVAILABLE
1198         return a|b; 
1199 #else
1200         return builtin_i2l(0);
1201 #endif
1202 }
1203
1204 s8 builtin_lxor (s8 a, s8 b) 
1205
1206 #if U8_AVAILABLE
1207         return a^b; 
1208 #else
1209         return builtin_i2l(0);
1210 #endif
1211 }
1212
1213 s8 builtin_lneg (s8 a) 
1214
1215 #if U8_AVAILABLE
1216         return -a;
1217 #else
1218         return builtin_i2l(0);
1219 #endif
1220 }
1221
1222 s4 builtin_lcmp (s8 a, s8 b) 
1223
1224 #if U8_AVAILABLE
1225         if (a<b) return -1;
1226         if (a>b) return 1;
1227         return 0;
1228 #else
1229         return 0;
1230 #endif
1231 }
1232
1233
1234
1235
1236
1237 /*********** Funktionen f"ur die Floating-Point-Operationen ******************/
1238
1239 float builtin_fadd (float a, float b)
1240 {
1241         if (isnanf(a)) return FLT_NAN;
1242         if (isnanf(b)) return FLT_NAN;
1243         if (finitef(a)) {
1244                 if (finitef(b)) return a+b;
1245                 else return b;
1246                 }
1247         else {
1248                 if (finitef(b)) return a;
1249                 else {
1250                         if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
1251                         else  return FLT_NAN;
1252                         }
1253                 }
1254 }
1255
1256 float builtin_fsub (float a, float b)
1257 {
1258         return builtin_fadd (a, builtin_fneg(b));
1259 }
1260
1261 float builtin_fmul (float a, float b)
1262 {
1263         if (isnanf(a)) return FLT_NAN;
1264         if (isnanf(b)) return FLT_NAN;
1265         if (finitef(a)) {
1266                 if (finitef(b)) return a*b;
1267                 else {
1268                         if (a==0) return FLT_NAN;
1269                              else return copysignf(b, copysignf(1.0, b)*a);
1270                         }
1271                 }
1272         else {
1273                 if (finitef(b)) {
1274                         if (b==0) return FLT_NAN;
1275                              else return copysignf(a, copysignf(1.0, a)*b);
1276                         }
1277                 else {
1278                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1279                         }
1280                 }
1281 }
1282
1283 float builtin_fdiv (float a, float b)
1284 {
1285         if (finitef(a) && finitef(b)) {
1286                 if (b != 0)
1287                         return a / b;
1288                 else {
1289                         if (a > 0)
1290                                 return FLT_POSINF;
1291                         else if (a < 0)
1292                                 return FLT_NEGINF;
1293                         }
1294                 }
1295         return FLT_NAN;
1296 }
1297
1298 float builtin_frem (float a, float b)
1299 {
1300
1301 /* return (float) builtin_drem((double) a, (double) b); */
1302
1303         float f;
1304
1305         if (finite((double) a) && finite((double) b)) {
1306                 f = a / b;
1307                 if (finite((double) f))
1308                         return fmodf(a, b);
1309                 return FLT_NAN;
1310                 }
1311         if (isnan((double) b))
1312                 return FLT_NAN;
1313         if (finite((double) a))
1314                 return a;
1315         return FLT_NAN;
1316
1317 /*      float f;
1318
1319         if (finitef(a) && finitef(b)) {
1320                 f = a / b;
1321                 if (finitef(f))
1322                         return a - floorf(f) * b;
1323                 return FLT_NAN;
1324                 }
1325         if (isnanf(b))
1326                 return FLT_NAN;
1327         if (finitef(a))
1328                 return a;
1329         return FLT_NAN; */
1330 }
1331
1332
1333 float builtin_fneg (float a)
1334 {
1335         if (isnanf(a)) return a;
1336         else {
1337                 if (finitef(a)) return -a;
1338                            else return copysignf(a,-copysignf(1.0, a));
1339                 }
1340 }
1341
1342 s4 builtin_fcmpl (float a, float b)
1343 {
1344         if (isnanf(a)) return -1;
1345         if (isnanf(b)) return -1;
1346         if (!finitef(a) || !finitef(b)) {
1347                 a = finitef(a) ? 0 : copysignf(1.0,  a);
1348                 b = finitef(b) ? 0 : copysignf(1.0, b);
1349                 }
1350         if (a>b) return 1;
1351         if (a==b) return 0;
1352         return -1;
1353 }
1354
1355 s4 builtin_fcmpg (float a, float b)
1356 {
1357         if (isnanf(a)) return 1;
1358         if (isnanf(b)) return 1;
1359         if (!finitef(a) || !finitef(b)) {
1360                 a = finitef(a) ? 0 : copysignf(1.0, a);
1361                 b = finitef(b) ? 0 : copysignf(1.0, b);
1362                 }
1363         if (a>b) return 1;
1364         if (a==b) return 0;
1365         return -1;
1366 }
1367
1368
1369
1370 /*********** Funktionen f"ur doppelt genaue Fliesskommazahlen ***************/
1371
1372 double builtin_dadd (double a, double b)
1373 {
1374         if (isnan(a)) return DBL_NAN;
1375         if (isnan(b)) return DBL_NAN;
1376         if (finite(a)) {
1377                 if (finite(b)) return a+b;
1378                 else return b;
1379                 }
1380         else {
1381                 if (finite(b)) return a;
1382                 else {
1383                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1384                         else  return DBL_NAN;
1385                         }
1386                 }
1387 }
1388
1389 double builtin_dsub (double a, double b)
1390 {
1391         return builtin_dadd (a, builtin_dneg(b));
1392 }
1393
1394 double builtin_dmul (double a, double b)
1395 {
1396         if (isnan(a)) return DBL_NAN;
1397         if (isnan(b)) return DBL_NAN;
1398         if (finite(a)) {
1399                 if (finite(b)) return a*b;
1400                 else {
1401                         if (a==0) return DBL_NAN;
1402                              else return copysign(b, copysign(1.0, b)*a);
1403                         }
1404                 }
1405         else {
1406                 if (finite(b)) {
1407                         if (b==0) return DBL_NAN;
1408                              else return copysign(a, copysign(1.0, a)*b);
1409                         }
1410                 else {
1411                         return copysign(a, copysign(1.0, a)*copysign(1.0, b));
1412                         }
1413                 }
1414 }
1415
1416 double builtin_ddiv (double a, double b)
1417 {
1418         if (finite(a) && finite(b)) {
1419                 if (b != 0)
1420                         return a / b;
1421                 else {
1422                         if (a > 0)
1423                                 return DBL_POSINF;
1424                         else if (a < 0)
1425                                 return DBL_NEGINF;
1426                         }
1427                 }
1428         return DBL_NAN;
1429 }
1430
1431 double builtin_drem (double a, double b)
1432 {
1433         double d;
1434
1435         if (finite(a) && finite(b)) {
1436                 d = a / b;
1437                 if (finite(d)) {
1438                         if ((d < 1.0) && (d > 0.0))
1439                                 return a;
1440                         return fmod(a, b);
1441                         }
1442                 return DBL_NAN;
1443                 }
1444         if (isnan(b))
1445                 return DBL_NAN;
1446         if (finite(a))
1447                 return a;
1448         return DBL_NAN;
1449 }
1450
1451 double builtin_dneg (double a)
1452 {
1453         if (isnan(a)) return a;
1454         else {
1455                 if (finite(a)) return -a;
1456                           else return copysign(a,-copysign(1.0, a));
1457                 }
1458 }
1459
1460 s4 builtin_dcmpl (double a, double b)
1461 {
1462         if (isnan(a)) return -1;
1463         if (isnan(b)) return -1;
1464         if (!finite(a) || !finite(b)) {
1465                 a = finite(a) ? 0 : copysign(1.0, a);
1466                 b = finite(b) ? 0 : copysign(1.0, b);
1467                 }
1468         if (a>b) return 1;
1469         if (a==b) return 0;
1470         return -1;
1471 }
1472
1473 s4 builtin_dcmpg (double a, double b)
1474 {
1475         if (isnan(a)) return 1;
1476         if (isnan(b)) return 1;
1477         if (!finite(a) || !finite(b)) {
1478                 a = finite(a) ? 0 : copysign(1.0, a);
1479                 b = finite(b) ? 0 : copysign(1.0, b);
1480                 }
1481         if (a>b) return 1;
1482         if (a==b) return 0;
1483         return -1;
1484 }
1485
1486
1487 /*********************** Umwandlungsoperationen ****************************/
1488
1489 s8 builtin_i2l (s4 i)
1490 {
1491 #if U8_AVAILABLE
1492         return i;
1493 #else
1494         s8 v; v.high = 0; v.low=i; return v;
1495 #endif
1496 }
1497
1498 float builtin_i2f (s4 a)
1499 {
1500 float f = (float) a;
1501 return f;
1502 }
1503
1504 double builtin_i2d (s4 a)
1505 {
1506 double d = (double) a;
1507 return d;
1508 }
1509
1510
1511 s4 builtin_l2i (s8 l)
1512 {
1513 #if U8_AVAILABLE
1514         return (s4) l;
1515 #else
1516         return l.low;
1517 #endif
1518 }
1519
1520 float builtin_l2f (s8 a)
1521 {
1522 #if U8_AVAILABLE
1523         float f = (float) a;
1524         return f;
1525 #else
1526         return 0.0;
1527 #endif
1528 }
1529
1530 double builtin_l2d (s8 a)
1531 {
1532 #if U8_AVAILABLE
1533         double d = (double) a;
1534         return d;
1535 #else
1536         return 0.0;
1537 #endif
1538 }
1539
1540
1541 s4 builtin_f2i(float a) 
1542 {
1543
1544 return builtin_d2i((double) a);
1545
1546 /*      float f;
1547         
1548         if (isnanf(a))
1549                 return 0;
1550         if (finitef(a)) {
1551                 if (a > 2147483647)
1552                         return 2147483647;
1553                 if (a < (-2147483648))
1554                         return (-2147483648);
1555                 return (s4) a;
1556                 }
1557         f = copysignf((float) 1.0, a);
1558         if (f > 0)
1559                 return 2147483647;
1560         return (-2147483648); */
1561 }
1562
1563
1564 s8 builtin_f2l (float a)
1565 {
1566
1567 return builtin_d2l((double) a);
1568
1569 /*      float f;
1570         
1571         if (finitef(a)) {
1572                 if (a > 9223372036854775807L)
1573                         return 9223372036854775807L;
1574                 if (a < (-9223372036854775808L))
1575                         return (-9223372036854775808L);
1576                 return (s8) a;
1577                 }
1578         if (isnanf(a))
1579                 return 0;
1580         f = copysignf((float) 1.0, a);
1581         if (f > 0)
1582                 return 9223372036854775807L;
1583         return (-9223372036854775808L); */
1584 }
1585
1586
1587 double builtin_f2d (float a)
1588 {
1589         if (finitef(a)) return (double) a;
1590         else {
1591                 if (isnanf(a)) return DBL_NAN;
1592                 else           return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
1593                 }
1594 }
1595
1596
1597 s4 builtin_d2i (double a) 
1598
1599         double d;
1600         
1601         if (finite(a)) {
1602                 if (a >= 2147483647)
1603                         return 2147483647;
1604                 if (a <= (-2147483648))
1605                         return (-2147483648);
1606                 return (s4) a;
1607                 }
1608         if (isnan(a))
1609                 return 0;
1610         d = copysign(1.0, a);
1611         if (d > 0)
1612                 return 2147483647;
1613         return (-2147483648);
1614 }
1615
1616
1617 s8 builtin_d2l (double a)
1618 {
1619         double d;
1620         
1621         if (finite(a)) {
1622                 if (a >= 9223372036854775807L)
1623                         return 9223372036854775807L;
1624                 if (a <= (-9223372036854775807L-1))
1625                         return (-9223372036854775807L-1);
1626                 return (s8) a;
1627                 }
1628         if (isnan(a))
1629                 return 0;
1630         d = copysign(1.0, a);
1631         if (d > 0)
1632                 return 9223372036854775807L;
1633         return (-9223372036854775807L-1);
1634 }
1635
1636
1637 float builtin_d2f (double a)
1638 {
1639         if (finite(a)) return (float) a;
1640         else {
1641                 if (isnan(a)) return FLT_NAN;
1642                 else          return copysignf (FLT_POSINF, (float) copysign(1.0, a));
1643                 }
1644 }
1645
1646
1647 /*
1648  * These are local overrides for various environment variables in Emacs.
1649  * Please do not remove this and leave it at the end of the file, where
1650  * Emacs will automagically detect them.
1651  * ---------------------------------------------------------------------
1652  * Local variables:
1653  * mode: c
1654  * indent-tabs-mode: t
1655  * c-basic-offset: 4
1656  * tab-width: 4
1657  * End:
1658  */