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