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