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