typedef a ptrint type to cast function pointers to int.
[cacao.git] / native.c
1 /* native.c - table of native functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28             Roman Obermaisser
29             Andreas Krall
30
31    The .hh files created with the header file generator are all
32    included here as are the C functions implementing these methods.
33
34    $Id: native.c 1567 2004-11-23 16:01:51Z twisti $
35
36 */
37
38
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <time.h>
42 #include <math.h>
43 #include <string.h>
44 #include <assert.h>
45 #include <sys/time.h>
46 #include <utime.h>
47
48 #include "config.h"
49 #include "exceptions.h"
50 #include "global.h"
51 #include "options.h"
52 #include "jni.h"
53 #include "native.h"
54 #include "builtin.h"
55 #include "asmpart.h"
56 #include "tables.h"
57 #include "loader.h"
58 #include "jni.h"
59 #include "jit/jit.h"
60 #include "toolbox/logging.h"
61 #include "toolbox/memory.h"
62 #include "threads/thread.h"
63 #include "threads/threadio.h"
64 #include "threads/locks.h"
65 #include "nat/java_lang_Throwable.h"
66
67
68 /* Include files for IO functions */
69
70 #include <fcntl.h>
71 #include <dirent.h>
72 #include <sys/types.h>
73 #ifdef _OSF_SOURCE 
74 #include <sys/mode.h>
75 #endif
76 #include <sys/stat.h>
77
78 #include "threads/threadio.h"
79
80 /* include table of native functions */
81
82 #include "nativetable.inc"
83
84
85 /* for java-string to char conversion */
86 #define MAXSTRINGSIZE 1000                          
87
88
89 /******************** systemclasses required for native methods ***************/
90
91 classinfo *class_java_lang_Class;
92 classinfo *class_java_lang_VMClass;
93 classinfo *class_java_lang_System;
94 classinfo *class_java_lang_ClassLoader;
95 classinfo *class_gnu_java_lang_SystemClassLoader;
96 classinfo *class_java_lang_SecurityManager;
97 classinfo *class_java_lang_Double;
98 classinfo *class_java_lang_Float;
99 classinfo *class_java_lang_Long;
100 classinfo *class_java_lang_Byte;
101 classinfo *class_java_lang_Short;
102 classinfo *class_java_lang_Boolean;
103 classinfo *class_java_lang_Void;
104 classinfo *class_java_lang_Character;
105 classinfo *class_java_lang_Integer;
106
107 methodinfo *method_vmclass_init;
108
109
110 /* the system classloader object */
111 struct java_lang_ClassLoader *SystemClassLoader = NULL;
112
113 /* for raising exceptions from native methods */
114 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
115 java_objectheader* _exceptionptr = NULL;
116 #endif
117
118 /************* use classinfo structure as java.lang.Class object **************/
119
120 void use_class_as_object(classinfo *c) 
121 {
122         if (!c->classvftbl) {
123                 c->header.vftbl = class_java_lang_Class->vftbl;
124                 c->classvftbl = true;
125         }
126              
127 }
128
129
130 /*************************** include native methods ***************************/ 
131
132 #ifdef USE_GTK 
133 #include "nat/GtkComponentPeer.c"
134 #include "nat/GtkScrollPanePeer.c"
135 #include "nat/GtkFileDialogPeer.c"
136 #endif
137
138
139 /************************** tables for methods ********************************/
140
141 #undef JOWENN_DEBUG
142 #undef JOWENN_DEBUG1
143
144 #ifdef STATIC_CLASSPATH
145 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
146
147 /* table for fast string comparison */
148 static nativecompref nativecomptable[NATIVETABLESIZE];
149
150 /* string comparsion table initialized */
151 static bool nativecompdone = false;
152 #endif
153
154 /******************************************************************************/
155
156 #include "natcalls.h"
157
158
159 /*********************** function: native_loadclasses **************************
160
161         load classes required for native methods        
162
163 *******************************************************************************/
164
165 void native_loadclasses()
166 {
167         static int classesLoaded = 0; /*temporary hack JoWenn*/
168
169         if (classesLoaded)
170                 return;
171
172         classesLoaded = 1;
173
174         class_java_lang_Cloneable =
175                 class_new(utf_new_char("java/lang/Cloneable"));
176         class_load(class_java_lang_Cloneable);
177         class_link(class_java_lang_Cloneable);
178
179         class_java_lang_Class =
180                 class_new(utf_new_char("java/lang/Class"));
181         class_load(class_java_lang_Class);
182         class_link(class_java_lang_Class);
183
184         class_java_lang_VMClass =
185                 class_new(utf_new_char("java/lang/VMClass"));
186         class_load(class_java_lang_VMClass);
187         class_link(class_java_lang_VMClass);
188
189         class_java_lang_ClassLoader =
190                 class_new(utf_new_char("java/lang/ClassLoader"));
191         class_load(class_java_lang_ClassLoader);
192         class_link(class_java_lang_ClassLoader);
193
194         /* load classes for wrapping primitive types */
195         class_java_lang_Double = class_new(utf_new_char("java/lang/Double"));
196         class_load(class_java_lang_Double);
197         class_link(class_java_lang_Double);
198
199         class_java_lang_Float = class_new(utf_new_char("java/lang/Float"));
200         class_load(class_java_lang_Float);
201         class_link(class_java_lang_Float);
202
203         class_java_lang_Character =     class_new(utf_new_char("java/lang/Character"));
204         class_load(class_java_lang_Character);
205         class_link(class_java_lang_Character);
206
207         class_java_lang_Integer = class_new(utf_new_char("java/lang/Integer"));
208         class_load(class_java_lang_Integer);
209         class_link(class_java_lang_Integer);
210
211         class_java_lang_Long = class_new(utf_new_char("java/lang/Long"));
212         class_load(class_java_lang_Long);
213         class_link(class_java_lang_Long);
214
215         class_java_lang_Byte = class_new(utf_new_char("java/lang/Byte"));
216         class_load(class_java_lang_Byte);
217         class_link(class_java_lang_Byte);
218
219         class_java_lang_Short = class_new(utf_new_char("java/lang/Short"));
220         class_load(class_java_lang_Short);
221         class_link(class_java_lang_Short);
222
223         class_java_lang_Boolean = class_new(utf_new_char("java/lang/Boolean"));
224         class_load(class_java_lang_Boolean);
225         class_link(class_java_lang_Boolean);
226
227         class_java_lang_Void = class_new(utf_new_char("java/lang/Void"));
228         class_load(class_java_lang_Void);
229         class_link(class_java_lang_Void);
230
231 }
232
233
234 /*****************************************************************************
235
236         create systemclassloader object and initialize instance fields  
237
238 ******************************************************************************/
239
240 void init_systemclassloader() 
241 {
242         log_text("init_systemclassloader");
243         if (!SystemClassLoader) {
244                 native_loadclasses();
245                 log_text("Initializing new system class loader");
246                 /* create object and call initializer */
247                 SystemClassLoader = (java_lang_ClassLoader *) native_new_and_init(class_new(utf_new_char("gnu/java/lang/SystemClassLoader")));
248
249                 /* systemclassloader has no parent */
250                 SystemClassLoader->parent      = NULL;
251                 SystemClassLoader->initialized = true;
252         }
253         log_text("leaving system class loader");
254 }
255
256
257 /*********************** Function: native_findfunction *************************
258
259         Looks up a method (must have the same class name, method name, descriptor
260         and 'static'ness) and returns a function pointer to it.
261         Returns: function pointer or NULL (if there is no such method)
262
263         Remark: For faster operation, the names/descriptors are converted from C
264                 strings to Unicode the first time this function is called.
265
266 *******************************************************************************/
267
268 functionptr native_findfunction(utf *cname, utf *mname, 
269                                                                 utf *desc, bool isstatic)
270 {
271 #ifdef STATIC_CLASSPATH
272         int i;
273         /* entry of table for fast string comparison */
274         struct nativecompref *n;
275         /* for warning message if no function is found */
276         char *buffer;                   
277         int buffer_len;
278
279         isstatic = isstatic ? true : false;
280         
281         if (!nativecompdone) {
282                 for (i = 0; i < NATIVETABLESIZE; i++) {
283                         nativecomptable[i].classname  = 
284                                 utf_new_char(nativetable[i].classname);
285                         nativecomptable[i].methodname = 
286                                 utf_new_char(nativetable[i].methodname);
287                         nativecomptable[i].descriptor = 
288                                 utf_new_char(nativetable[i].descriptor);
289                         nativecomptable[i].isstatic   = 
290                                 nativetable[i].isstatic;
291                         nativecomptable[i].func       = 
292                                 nativetable[i].func;
293                 }
294                 nativecompdone = true;
295         }
296
297 #ifdef JOWENN_DEBUG
298         buffer_len = 
299                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
300         
301         buffer = MNEW(char, buffer_len);
302
303         strcpy(buffer, "searching matching function in native table:");
304         utf_sprint(buffer+strlen(buffer), mname);
305         strcpy(buffer+strlen(buffer), ": ");
306         utf_sprint(buffer+strlen(buffer), desc);
307         strcpy(buffer+strlen(buffer), " for class ");
308         utf_sprint(buffer+strlen(buffer), cname);
309
310         log_text(buffer);       
311
312         MFREE(buffer, char, buffer_len);
313 #endif
314                 
315         for (i = 0; i < NATIVETABLESIZE; i++) {
316                 n = &(nativecomptable[i]);
317
318                 if (cname == n->classname && mname == n->methodname &&
319                     desc == n->descriptor && isstatic == n->isstatic)
320                         return n->func;
321 #ifdef JOWENN_DEBUG
322                         else {
323                                 if (cname == n->classname && mname == n->methodname )  log_text("static and descriptor mismatch");
324                         
325                                 else {
326                                         buffer_len = 
327                                           utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
328         
329                                         buffer = MNEW(char, buffer_len);
330
331                                         strcpy(buffer, "comparing with:");
332                                         utf_sprint(buffer+strlen(buffer), n->methodname);
333                                         strcpy (buffer+strlen(buffer), ": ");
334                                         utf_sprint(buffer+strlen(buffer), n->descriptor);
335                                         strcpy(buffer+strlen(buffer), " for class ");
336                                         utf_sprint(buffer+strlen(buffer), n->classname);
337
338                                         log_text(buffer);       
339
340                                         MFREE(buffer, char, buffer_len);
341                                 }
342                         } 
343 #endif
344         }
345
346                 
347         /* no function was found, display warning */
348
349         buffer_len = 
350                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
351
352         buffer = MNEW(char, buffer_len);
353
354         strcpy(buffer, "warning: native function ");
355         utf_sprint(buffer + strlen(buffer), mname);
356         strcpy(buffer + strlen(buffer), ": ");
357         utf_sprint(buffer + strlen(buffer), desc);
358         strcpy(buffer + strlen(buffer), " not found in class ");
359         utf_sprint(buffer + strlen(buffer), cname);
360
361         log_text(buffer);       
362
363         MFREE(buffer, char, buffer_len);
364
365 /*      exit(1); */
366
367         /* keep compiler happy */
368         return NULL;
369 #else
370 /* dynamic classpath */
371   return 0;
372 #endif
373 }
374
375
376 /********************** function: javastring_new *******************************
377
378         creates a new object of type java/lang/String with the text of 
379         the specified utf8-string
380
381         return: pointer to the string or NULL if memory is exhausted.   
382
383 *******************************************************************************/
384
385 java_lang_String *javastring_new(utf *u)
386 {
387         char *utf_ptr;                  /* current utf character in utf string    */
388         u4 utflength;                   /* length of utf-string if uncompressed   */
389         java_lang_String *s;                /* result-string                          */
390         java_chararray *a;
391         s4 i;
392
393         if (!u) {
394                 *exceptionptr = new_nullpointerexception();
395                 return NULL;
396         }
397
398         utf_ptr = u->text;
399         utflength = utf_strlen(u);
400
401         s = (java_lang_String *) builtin_new(class_java_lang_String);
402         a = builtin_newarray_char(utflength);
403
404         /* javastring or character-array could not be created */
405         if (!a || !s)
406                 return NULL;
407
408         /* decompress utf-string */
409         for (i = 0; i < utflength; i++)
410                 a->data[i] = utf_nextu2(&utf_ptr);
411         
412         /* set fields of the javastring-object */
413         s->value  = a;
414         s->offset = 0;
415         s->count  = utflength;
416
417         return s;
418 }
419
420
421 /********************** function: javastring_new_char **************************
422
423         creates a new java/lang/String object which contains the convertet
424         C-string passed via text.
425
426         return: the object pointer or NULL if memory is exhausted.
427
428 *******************************************************************************/
429
430 java_lang_String *javastring_new_char(char *text)
431 {
432         s4 i;
433         s4 len;                /* length of the string */
434         java_lang_String *s;   /* result-string */
435         java_chararray *a;
436
437         if (!text) {
438                 *exceptionptr = new_nullpointerexception();
439                 return NULL;
440         }
441
442         len = strlen(text);
443
444         s = (java_lang_String *) builtin_new(class_java_lang_String);
445         a = builtin_newarray_char(len);
446
447         /* javastring or character-array could not be created */
448         if (!a || !s)
449                 return NULL;
450
451         /* copy text */
452         for (i = 0; i < len; i++)
453                 a->data[i] = text[i];
454         
455         /* set fields of the javastring-object */
456         s->value  = a;
457         s->offset = 0;
458         s->count  = len;
459
460         return s;
461 }
462
463
464 /************************* function javastring_tochar **************************
465
466         converts a Java string into a C string.
467         
468         return: pointer to C string
469         
470         Caution: every call of this function overwrites the previous string !!!
471         
472 *******************************************************************************/
473
474 static char stringbuffer[MAXSTRINGSIZE];
475
476 char *javastring_tochar(java_objectheader *so) 
477 {
478         java_lang_String *s = (java_lang_String *) so;
479         java_chararray *a;
480         s4 i;
481         
482         if (!s)
483                 return "";
484
485         a = s->value;
486
487         if (!a)
488                 return "";
489
490         if (s->count > MAXSTRINGSIZE)
491                 return "";
492
493         for (i = 0; i < s->count; i++)
494                 stringbuffer[i] = a->data[s->offset + i];
495
496         stringbuffer[i] = '\0';
497
498         return stringbuffer;
499 }
500
501
502 /****************** function class_findfield_approx ****************************
503         
504         searches in 'classinfo'-structure for a field with the
505         specified name
506
507 *******************************************************************************/
508  
509 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
510 {
511         s4 i;
512
513         for (i = 0; i < c->fieldscount; i++) {
514                 /* compare field names */
515                 if ((c->fields[i].name == name))
516                         return &(c->fields[i]);
517         }
518
519         /* field was not found, raise exception */      
520         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
521
522         return NULL;
523 }
524
525
526 s4 class_findfield_index_approx(classinfo *c, utf *name)
527 {
528         s4 i;
529
530         for (i = 0; i < c->fieldscount; i++) {
531                 /* compare field names */
532                 if ((c->fields[i].name == name))
533                         return i;
534         }
535
536         /* field was not found, raise exception */      
537         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
538
539         return -1;
540 }
541
542
543 /********************** function: native_new_and_init *************************
544
545         Creates a new object on the heap and calls the initializer.
546         Returns the object pointer or NULL if memory is exhausted.
547                         
548 *******************************************************************************/
549
550 java_objectheader *native_new_and_init(classinfo *c)
551 {
552         methodinfo *m;
553         java_objectheader *o;
554
555         if (!c)
556                 return *exceptionptr;
557
558         o = builtin_new(c);                 /* create object                      */
559         
560         if (!o)
561                 return NULL;
562
563         /* find initializer */
564
565         m = class_findmethod(c,
566                                                  utf_new_char("<init>"),
567                                                  utf_new_char("()V"));
568                                                       
569         if (!m) {                           /* initializer not found              */
570                 if (opt_verbose) {
571                         char logtext[MAXLOGTEXT];
572                         sprintf(logtext, "Warning: class has no instance-initializer: ");
573                         utf_sprint_classname(logtext + strlen(logtext), c->name);
574                         log_text(logtext);
575                 }
576                 return o;
577         }
578
579         /* call initializer */
580
581         asm_calljavafunction(m, o, NULL, NULL, NULL);
582
583         return o;
584 }
585
586
587 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
588 {
589         methodinfo *m;
590         java_objectheader *o;
591
592         if (!c)
593                 return *exceptionptr;
594
595         o = builtin_new(c);          /* create object          */
596
597         if (!o)
598                 return NULL;
599
600         /* find initializer */
601
602         m = class_findmethod(c,
603                                                  utf_new_char("<init>"),
604                                                  utf_new_char("(Ljava/lang/String;)V"));
605                                                       
606         if (!m) {                                       /* initializer not found  */
607                 if (opt_verbose) {
608                         char logtext[MAXLOGTEXT];
609                         sprintf(logtext, "Warning: class has no instance-initializer: ");
610                         utf_sprint_classname(logtext + strlen(logtext), c->name);
611                         log_text(logtext);
612                 }
613                 return o;
614         }
615
616         /* call initializer */
617
618         asm_calljavafunction(m, o, s, NULL, NULL);
619
620         return o;
621 }
622
623
624 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
625 {
626         methodinfo *m;
627         java_objectheader *o;
628
629         if (!c)
630                 return *exceptionptr;
631
632         o = builtin_new(c);          /* create object          */
633         
634         if (!o) return NULL;
635
636         /* find initializer */
637
638         m = class_findmethod(c,
639                                                  utf_new_char("<init>"),
640                                                  utf_new_char("(I)V"));
641                                                       
642         if (!m) {                                       /* initializer not found  */
643                 if (opt_verbose) {
644                         char logtext[MAXLOGTEXT];
645                         sprintf(logtext, "Warning: class has no instance-initializer: ");
646                         utf_sprint_classname(logtext + strlen(logtext), c->name);
647                         log_text(logtext);
648                 }
649                 return o;
650         }
651
652         /* call initializer */
653
654 #if defined(__I386__) || defined(__POWERPC__)
655         asm_calljavafunction(m, o, (void *) i, NULL, NULL);
656 #else
657         asm_calljavafunction(m, o, (void *) (s8) i, NULL, NULL);
658 #endif
659
660         return o;
661 }
662
663
664 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
665 {
666         methodinfo *m;
667         java_objectheader *o;
668
669         if (!c)
670                 return *exceptionptr;
671
672         o = builtin_new(c);          /* create object          */
673         
674         if (!o) return NULL;
675
676         /* find initializer */
677
678         m = class_findmethod(c,
679                                                  utf_new_char("<init>"),
680                                                  utf_new_char("(Ljava/lang/Throwable;)V"));
681                                                       
682         if (!m) {                                       /* initializer not found  */
683                 if (opt_verbose) {
684                         char logtext[MAXLOGTEXT];
685                         sprintf(logtext, "Warning: class has no instance-initializer: ");
686                         utf_sprint_classname(logtext + strlen(logtext), c->name);
687                         log_text(logtext);
688                 }
689                 return o;
690         }
691
692         /* call initializer */
693
694         asm_calljavafunction(m, o, t, NULL, NULL);
695
696         return o;
697 }
698
699
700 /******************** function: stringtable_update ****************************
701
702         traverses the javastring hashtable and sets the vftbl-entries of
703         javastrings which were temporarily set to NULL, because 
704         java.lang.Object was not yet loaded
705
706 *******************************************************************************/
707  
708 void stringtable_update ()
709 {
710         java_lang_String *js;   
711         java_chararray *a;
712         literalstring *s;       /* hashtable entry */
713         int i;
714
715         for (i = 0; i < string_hash.size; i++) {
716                 s = string_hash.ptr[i];
717                 if (s) {
718                         while (s) {
719                                                                 
720                                 js = (java_lang_String *) s->string;
721                                 
722                                 if (!js || !js->value) 
723                                         /* error in hashtable found */
724                                         panic("invalid literalstring in hashtable");
725
726                                 a = js->value;
727
728                                 if (!js->header.vftbl) 
729                                         /* vftbl of javastring is NULL */ 
730                                         js->header.vftbl = class_java_lang_String->vftbl;
731
732                                 if (!a->header.objheader.vftbl) 
733                                         /* vftbl of character-array is NULL */ 
734                                         a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
735
736                                 /* follow link in external hash chain */
737                                 s = s->hashlink;
738                         }       
739                 }               
740         }
741 }
742
743
744 /************************* function: u2_utflength ***************************
745
746         returns the utf length in bytes of a u2 array 
747
748 *****************************************************************************/
749
750 u4 u2_utflength(u2 *text, u4 u2_length)
751 {
752         u4 result_len =  0;  /* utf length in bytes  */
753         u2 ch;               /* current unicode character */
754         u4 len;
755         
756         for (len = 0; len < u2_length; len++) {
757                 /* next unicode character */
758                 ch = *text++;
759           
760                 /* determine bytes required to store unicode character as utf */
761                 if (ch && (ch < 0x80)) 
762                         result_len++;
763                 else if (ch < 0x800)
764                         result_len += 2;        
765                 else 
766                         result_len += 3;        
767         }
768
769     return result_len;
770 }
771
772
773 /********************* function: utf_new_u2 ***********************************
774
775         make utf symbol from u2 array, 
776         if isclassname is true '.' is replaced by '/'
777
778 *******************************************************************************/
779
780 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
781 {
782         char *buffer; /* memory buffer for  unicode characters */
783         char *pos;    /* pointer to current position in buffer */
784         u4 left;      /* unicode characters left */
785         u4 buflength; /* utf length in bytes of the u2 array  */
786         utf *result;  /* resulting utf-string */
787         int i;          
788
789         /* determine utf length in bytes and allocate memory */
790         /* printf("utf_new_u2: unicode_length=%d\n",unicode_length);            */
791         buflength = u2_utflength(unicode_pos, unicode_length); 
792         buffer    = MNEW(char, buflength);
793  
794         left = buflength;
795         pos  = buffer;
796
797         for (i = 0; i++ < unicode_length; unicode_pos++) {
798                 /* next unicode character */
799                 u2 c = *unicode_pos;
800                 
801                 if ((c != 0) && (c < 0x80)) {
802                         /* 1 character */       
803                         left--;
804                 if ((int) left < 0) break;
805                         /* convert classname */
806                         if (isclassname && c == '.')
807                                 *pos++ = '/';
808                         else
809                                 *pos++ = (char) c;
810
811                 } else if (c < 0x800) {             
812                         /* 2 characters */                              
813                 unsigned char high = c >> 6;
814                 unsigned char low  = c & 0x3F;
815                         left = left - 2;
816                 if ((int) left < 0) break;
817                 *pos++ = high | 0xC0; 
818                 *pos++ = low  | 0x80;     
819
820                 } else {         
821                 /* 3 characters */                              
822                 char low  = c & 0x3f;
823                 char mid  = (c >> 6) & 0x3F;
824                 char high = c >> 12;
825                         left = left - 3;
826                 if ((int) left < 0) break;
827                 *pos++ = high | 0xE0; 
828                 *pos++ = mid  | 0x80;  
829                 *pos++ = low  | 0x80;   
830                 }
831         }
832         
833         /* insert utf-string into symbol-table */
834         result = utf_new(buffer,buflength);
835
836         MFREE(buffer, char, buflength);
837
838         return result;
839 }
840
841
842 /********************* function: javastring_toutf *****************************
843
844         make utf symbol from javastring
845
846 *******************************************************************************/
847
848 utf *javastring_toutf(java_lang_String *string, bool isclassname)
849 {
850         java_lang_String *str = (java_lang_String *) string;
851
852 /*      printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count); */
853 /*      fflush(stdout); */
854
855         return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
856 }
857
858
859 /********************* function: literalstring_u2 *****************************
860
861     searches for the javastring with the specified u2-array in 
862     the string hashtable, if there is no such string a new one is 
863     created 
864
865     if copymode is true a copy of the u2-array is made
866
867 *******************************************************************************/
868
869 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
870                                                                         bool copymode)
871 {
872     literalstring *s;                /* hashtable element */
873     java_lang_String *js;            /* u2-array wrapped in javastring */
874     java_chararray *stringdata;      /* copy of u2-array */      
875     u4 key;
876     u4 slot;
877     u2 i;
878
879 /* #define DEBUG_LITERALSTRING_U2 */
880 #ifdef DEBUG_LITERALSTRING_U2
881     printf("literalstring_u2: length=%d, offset=%d\n", length, offset);
882         fflush(stdout);
883 #endif
884     
885     /* find location in hashtable */
886     key  = unicode_hashkey(a->data + offset, length);
887     slot = key & (string_hash.size - 1);
888     s    = string_hash.ptr[slot];
889
890     while (s) {
891                 js = (java_lang_String *) s->string;
892
893                 if (length == js->count) {
894                         /* compare text */
895                         for (i = 0; i < length; i++) {
896                                 if (a->data[offset + i] != js->value->data[i])
897                                         goto nomatch;
898                         }
899
900                         /* string already in hashtable, free memory */
901                         if (!copymode)
902                                 mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
903
904 #ifdef DEBUG_LITERALSTRING_U2
905                         printf("literalstring_u2: foundentry at %p\n", js);
906                         utf_display(javastring_toutf(js, 0));
907                         printf("\n\n");
908                         fflush(stdout);
909 #endif
910                         return (java_objectheader *) js;
911                 }
912
913         nomatch:
914                 /* follow link in external hash chain */
915                 s = s->hashlink;
916     }
917
918     if (copymode) {
919                 /* create copy of u2-array for new javastring */
920                 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
921                 stringdata = mem_alloc(arraysize);
922 /*              memcpy(stringdata, a, arraysize); */
923                 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
924                 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
925
926     } else {
927                 stringdata = a;
928         }
929
930     /* location in hashtable found, complete arrayheader */
931     stringdata->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
932     stringdata->header.size = length;
933
934         /* if we use eager loading, we have to check loaded String class */
935         if (opt_eager) {
936                 class_java_lang_String =
937                         class_new_intern(utf_new_char("java/lang/String"));
938
939                 if (!class_load(class_java_lang_String))
940                         return NULL;
941
942                 list_addfirst(&unlinkedclasses, class_java_lang_String);
943         }
944
945         /* create new javastring */
946         js = NEW(java_lang_String);
947 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
948         initObjectLock(&js->header);
949 #endif
950         js->header.vftbl = class_java_lang_String->vftbl;
951         js->value  = stringdata;
952         js->offset = 0;
953         js->count  = length;
954
955 #ifdef DEBUG_LITERALSTRING_U2
956         printf("literalstring_u2: newly created at %p\n", js);
957         utf_display(javastring_toutf(js, 0));
958         printf("\n\n");
959         fflush(stdout);
960 #endif
961                         
962         /* create new literalstring */
963         s = NEW(literalstring);
964         s->hashlink = string_hash.ptr[slot];
965         s->string   = (java_objectheader *) js;
966         string_hash.ptr[slot] = s;
967
968         /* update number of hashtable entries */
969         string_hash.entries++;
970
971         /* reorganization of hashtable */       
972         if (string_hash.entries > (string_hash.size * 2)) {
973                 /* reorganization of hashtable, average length of 
974                    the external chains is approx. 2                */  
975
976                 u4 i;
977                 literalstring *s;
978                 hashtable newhash; /* the new hashtable */
979       
980                 /* create new hashtable, double the size */
981                 init_hashtable(&newhash, string_hash.size * 2);
982                 newhash.entries = string_hash.entries;
983       
984                 /* transfer elements to new hashtable */
985                 for (i = 0; i < string_hash.size; i++) {
986                         s = string_hash.ptr[i];
987                         while (s) {
988                                 literalstring *nexts = s->hashlink;
989                                 js   = (java_lang_String *) s->string;
990                                 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
991           
992                                 s->hashlink = newhash.ptr[slot];
993                                 newhash.ptr[slot] = s;
994         
995                                 /* follow link in external hash chain */  
996                                 s = nexts;
997                         }
998                 }
999         
1000                 /* dispose old table */ 
1001                 MFREE(string_hash.ptr, void*, string_hash.size);
1002                 string_hash = newhash;
1003         }
1004
1005         return (java_objectheader *) js;
1006 }
1007
1008
1009 /******************** Function: literalstring_new *****************************
1010
1011     creates a new javastring with the text of the utf-symbol
1012     and inserts it into the string hashtable
1013
1014 *******************************************************************************/
1015
1016 java_objectheader *literalstring_new(utf *u)
1017 {
1018     char *utf_ptr = u->text;         /* pointer to current unicode character in utf string */
1019     u4 utflength  = utf_strlen(u);   /* length of utf-string if uncompressed */
1020     java_chararray *a;               /* u2-array constructed from utf string */
1021     u4 i;
1022
1023     /* allocate memory */ 
1024     a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
1025
1026     /* convert utf-string to u2-array */
1027     for (i = 0; i < utflength; i++)
1028                 a->data[i] = utf_nextu2(&utf_ptr);
1029
1030     return literalstring_u2(a, utflength, 0, false);
1031 }
1032
1033
1034 /********************** function: literalstring_free **************************
1035
1036         removes a javastring from memory                       
1037
1038 ******************************************************************************/
1039
1040 void literalstring_free(java_objectheader* sobj)
1041 {
1042         java_lang_String *s = (java_lang_String *) sobj;
1043         java_chararray *a = s->value;
1044
1045         /* dispose memory of java.lang.String object */
1046         FREE(s, java_lang_String);
1047
1048         /* dispose memory of java-characterarray */
1049         FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
1050 }
1051
1052
1053 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
1054 {
1055     *dest = src;
1056 #if 0
1057     /* XXX this kind of copying does not work (in the general
1058      * case). The interface tables would have to be copied, too. I
1059      * don't see why we should make a copy anyway. -Edwin
1060      */
1061         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1062         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1063         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1064 #endif
1065 }
1066
1067
1068 /******************************************************************************************                                                                                                             
1069
1070         creates method signature (excluding return type) from array of 
1071         class-objects representing the parameters of the method 
1072
1073 *******************************************************************************************/
1074
1075
1076 utf *create_methodsig(java_objectarray* types, char *retType)
1077 {
1078     char *buffer;       /* buffer for building the desciptor */
1079     char *pos;          /* current position in buffer */
1080     utf *result;        /* the method signature */
1081     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1082     u4 i, j;
1083  
1084     if (!types) return NULL;
1085
1086     /* determine required buffer-size */    
1087     for (i = 0; i < types->header.size; i++) {
1088                 classinfo *c = (classinfo *) types->data[i];
1089                 buffer_size  = buffer_size + c->name->blength + 2;
1090     }
1091
1092     if (retType) buffer_size += strlen(retType);
1093
1094     /* allocate buffer */
1095     buffer = MNEW(char, buffer_size);
1096     pos    = buffer;
1097     
1098     /* method-desciptor starts with parenthesis */
1099     *pos++ = '(';
1100
1101     for (i = 0; i < types->header.size; i++) {
1102                 char ch;           
1103
1104                 /* current argument */
1105             classinfo *c = (classinfo *) types->data[i];
1106
1107             /* current position in utf-text */
1108             char *utf_ptr = c->name->text; 
1109             
1110             /* determine type of argument */
1111             if ((ch = utf_nextu2(&utf_ptr)) == '[') {
1112                 /* arrayclass */
1113                 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1114                                 *pos++ = *utf_ptr; /* copy text */
1115                         }
1116
1117             } else {            
1118                         /* check for primitive types */
1119                         for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1120                                 char *utf_pos   = utf_ptr - 1;
1121                                 char *primitive = primitivetype_table[j].wrapname;
1122
1123                                 /* compare text */
1124                                 while (utf_pos < utf_end(c->name)) {
1125                                         if (*utf_pos++ != *primitive++) goto nomatch;
1126                                 }
1127
1128                                 /* primitive type found */
1129                                 *pos++ = primitivetype_table[j].typesig;
1130                                 goto next_type;
1131
1132                         nomatch:
1133                                 ;
1134                         }
1135
1136                         /* no primitive type and no arrayclass, so must be object */
1137                         *pos++ = 'L';
1138
1139                         /* copy text */
1140                         for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1141                                 *pos++ = *utf_ptr;
1142                         }
1143
1144                         *pos++ = ';';
1145
1146                 next_type:
1147                         ;
1148                 }  
1149     }       
1150
1151     *pos++ = ')';
1152
1153     if (retType) {
1154                 for (i = 0; i < strlen(retType); i++) {
1155                         *pos++ = retType[i];
1156                 }
1157     }
1158
1159     /* create utf-string */
1160     result = utf_new(buffer, (pos - buffer));
1161     MFREE(buffer, char, buffer_size);
1162
1163     return result;
1164 }
1165
1166
1167 /******************************************************************************************
1168
1169         retrieve the next argument or returntype from a descriptor
1170         and return the corresponding class 
1171
1172 *******************************************************************************************/
1173
1174 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1175 {
1176     classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1177                                          (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1178     if (!c)
1179         /* unknown type */
1180         panic("illegal descriptor");
1181
1182     if (skip) return NULL;
1183
1184     use_class_as_object(c);
1185     return c;
1186 }
1187
1188
1189 /* get_parametertypes **********************************************************
1190
1191    use the descriptor of a method to generate a java/lang/Class array
1192    which contains the classes of the parametertypes of the method
1193
1194 *******************************************************************************/
1195
1196 java_objectarray* get_parametertypes(methodinfo *m) 
1197 {
1198     utf  *descr    =  m->descriptor;    /* method-descriptor */ 
1199     char *utf_ptr  =  descr->text;      /* current position in utf-text */
1200     char *desc_end =  utf_end(descr);   /* points behind utf string     */
1201     java_objectarray* result;
1202     int parametercount = 0;
1203     int i;
1204
1205     /* skip '(' */
1206     utf_nextu2(&utf_ptr);
1207   
1208     /* determine number of parameters */
1209     while (*utf_ptr != ')') {
1210         get_type(&utf_ptr, desc_end, true);
1211                 parametercount++;
1212     }
1213
1214     /* create class-array */
1215     result = builtin_anewarray(parametercount, class_java_lang_Class);
1216
1217     utf_ptr = descr->text;
1218     utf_nextu2(&utf_ptr);
1219
1220     /* get returntype classes */
1221     for (i = 0; i < parametercount; i++)
1222             result->data[i] =
1223                         (java_objectheader *) get_type(&utf_ptr, desc_end, false);
1224
1225     return result;
1226 }
1227
1228
1229 /* get_exceptiontypes **********************************************************
1230
1231    get the exceptions which can be thrown by a method
1232
1233 *******************************************************************************/
1234
1235 java_objectarray* get_exceptiontypes(methodinfo *m)
1236 {
1237     u2 excount;
1238     u2 i;
1239     java_objectarray *result;
1240
1241         excount = m->thrownexceptionscount;
1242
1243     /* create class-array */
1244     result = builtin_anewarray(excount, class_java_lang_Class);
1245
1246     for (i = 0; i < excount; i++) {
1247                 java_objectheader *o = (java_objectheader *) (m->thrownexceptions[i]);
1248                 use_class_as_object((classinfo *) o);
1249                 result->data[i] = o;
1250     }
1251
1252     return result;
1253 }
1254
1255
1256
1257
1258
1259 /******************************************************************************************
1260
1261         get the returntype class of a method
1262
1263 *******************************************************************************************/
1264
1265 classinfo *get_returntype(methodinfo *m) 
1266 {
1267         char *utf_ptr;   /* current position in utf-text */
1268         char *desc_end;  /* points behind utf string     */
1269         utf *desc = m->descriptor; /* method-descriptor  */
1270
1271         utf_ptr  = desc->text;
1272         desc_end = utf_end(desc);
1273
1274         /* ignore parametertypes */
1275         while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1276                 /* skip */ ;
1277
1278         return get_type(&utf_ptr,desc_end, false);
1279 }
1280
1281
1282 /*****************************************************************************/
1283 /*****************************************************************************/
1284
1285
1286 /*--------------------------------------------------------*/
1287 void printNativeCall(nativeCall nc) {
1288   int i,j;
1289
1290   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1291   for (i=0; i<nc.methCnt; i++) {  
1292       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1293
1294     for (j=0; j<nc.callCnt[i]; j++) {  
1295         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1296         nc.methods[i].methodCalls[j].classname, 
1297         nc.methods[i].methodCalls[j].methodname, 
1298         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1299       }
1300     }
1301   printf("-+++++--------------------\n");fflush(stdout);
1302 }
1303
1304 /*--------------------------------------------------------*/
1305 void printCompNativeCall(nativeCompCall nc) {
1306   int i,j;
1307   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
1308   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1309   utf_display(nc.classname); fflush(stdout);
1310   
1311   for (i=0; i<nc.methCnt; i++) {  
1312     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1313     utf_display(nc.methods[i].methodname); fflush(stdout);
1314     utf_display(nc.methods[i].descriptor);fflush(stdout);
1315     printf("\n");fflush(stdout);
1316
1317     for (j=0; j<nc.callCnt[i]; j++) {  
1318       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1319         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1320         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1321         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1322         printf("\n");fflush(stdout);
1323       }
1324     }
1325 printf("---------------------\n");fflush(stdout);
1326 }
1327
1328
1329 /*--------------------------------------------------------*/
1330 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1331 {
1332     int i = 0;
1333     int j = 0;
1334     int cnt = 0;
1335     classMeth mc;
1336     mc.i_class = i;
1337     mc.j_method = j;
1338     mc.methCnt = cnt;
1339
1340     return mc;
1341 }
1342
1343 /*--------------------------------------------------------*/
1344 nativeCall* findNativeClassCalls(char *aclassname ) {
1345 int i;
1346
1347 for (i=0;i<NATIVECALLSSIZE; i++) {
1348    /* convert table to utf later to speed up search */ 
1349    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1350         return &nativeCalls[i];
1351    }
1352
1353 return NULL;
1354 }
1355 /*--------------------------------------------------------*/
1356 /*--------------------------------------------------------*/
1357 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1358   int i,j;
1359
1360
1361   ncc->classname = utf_new_char(nc.classname); 
1362   ncc->methCnt = nc.methCnt;
1363   
1364   for (i=0; i<nc.methCnt; i++) {  
1365     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1366     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1367     ncc->callCnt[i] = nc.callCnt[i];
1368
1369     for (j=0; j<nc.callCnt[i]; j++) {  
1370
1371         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1372
1373         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1374           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1375           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1376           }
1377         else {
1378           ncc->methods[i].methodCalls[j].methodname = NULL;
1379           ncc->methods[i].methodCalls[j].descriptor = NULL;
1380           }
1381       }
1382     }
1383 }
1384
1385
1386
1387 /*--------------------------------------------------------*/
1388
1389 bool natcall2utf(bool natcallcompdone) {
1390 int i;
1391
1392 if (natcallcompdone) 
1393         return true;
1394
1395 for (i=0;i<NATIVECALLSSIZE; i++) {
1396    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1397    }
1398
1399 return true;
1400 }
1401
1402 /*--------------------------------------------------------*/
1403
1404
1405 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end, classinfo **start)
1406 {
1407 #if defined(__GNUC__)
1408 #warning platform dependend
1409 #endif
1410         java_objectarray *tmpArray;
1411         int i;
1412         classinfo **current;
1413         classinfo *c;
1414         size_t size;
1415
1416         size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
1417
1418         /*printf("end %p, start %p, size %ld\n",end,start,size);*/
1419         if (!class_java_lang_Class)
1420                 class_java_lang_Class = class_new(utf_new_char("java/lang/Class"));
1421
1422         if (!class_java_lang_SecurityManager)
1423                 class_java_lang_SecurityManager =
1424                         class_new(utf_new_char("java/lang/SecurityManager"));
1425
1426         if (size > 0) {
1427                 if (start == class_java_lang_SecurityManager) {
1428                         size--;
1429                         start--;
1430                 }
1431         }
1432
1433         tmpArray =
1434                 builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
1435
1436         for(i = 0, current = start; i < size; i++, current--) {
1437                 c = *current;
1438                 /*              printf("%d\n",i);
1439                 utf_display(c->name);*/
1440                 use_class_as_object(c);
1441                 tmpArray->data[i] = (java_objectheader *) c;
1442         }
1443
1444         return tmpArray;
1445 }
1446
1447
1448 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end, classinfo **start)
1449 {
1450 #if defined(__GNUC__)
1451 #warning platform dependend
1452 #endif
1453         int i;
1454         classinfo **current;
1455         classinfo *c;
1456         classinfo *privilegedAction;
1457         size_t size;
1458
1459         size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
1460
1461         /*      log_text("builtin_asm_getclassloader");
1462         printf("end %p, start %p, size %ld\n",end,start,size);*/
1463
1464         if (!class_java_lang_SecurityManager)
1465                 class_java_lang_SecurityManager =
1466                         class_new(utf_new_char("java/lang/SecurityManager"));
1467
1468         if (size > 0) {
1469                 if (start == class_java_lang_SecurityManager) {
1470                         size--;
1471                         start--;
1472                 }
1473         }
1474
1475         privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
1476
1477         for(i = 0, current = start; i < size; i++, current--) {
1478                 c = *current;
1479
1480                 if (c == privilegedAction)
1481                         return NULL;
1482
1483                 if (c->classloader)
1484                         return (java_lang_ClassLoader *) c->classloader;
1485         }
1486
1487         return NULL;
1488
1489         /*
1490         log_text("Java_java_lang_VMSecurityManager_currentClassLoader");
1491         init_systemclassloader();
1492
1493         return SystemClassLoader;*/
1494 }
1495
1496
1497 /*
1498  * These are local overrides for various environment variables in Emacs.
1499  * Please do not remove this and leave it at the end of the file, where
1500  * Emacs will automagically detect them.
1501  * ---------------------------------------------------------------------
1502  * Local variables:
1503  * mode: c
1504  * indent-tabs-mode: t
1505  * c-basic-offset: 4
1506  * tab-width: 4
1507  * End:
1508  */