9db5a496478a0933735ae51a9bd3406ae87e44e5
[cacao.git] / src / native / native.c
1 /* native.c - table of native functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28             Roman Obermaisser
29             Andreas Krall
30
31    The .hh files created with the header file generator are all
32    included here as are the C functions implementing these methods.
33
34    $Id: native.c 1444 2004-11-05 13:54:52Z twisti $
35
36 */
37
38
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <time.h>
42 #include <math.h>
43 #include <string.h>
44 #include <assert.h>
45 #include <sys/time.h>
46 #include <utime.h>
47
48 #include "config.h"
49 #include "exceptions.h"
50 #include "global.h"
51 #include "options.h"
52 #include "jni.h"
53 #include "native.h"
54 #include "builtin.h"
55 #include "asmpart.h"
56 #include "tables.h"
57 #include "loader.h"
58 #include "jni.h"
59 #include "jit/jit.h"
60 #include "toolbox/logging.h"
61 #include "toolbox/memory.h"
62 #include "threads/thread.h"
63 #include "threads/threadio.h"
64 #include "threads/locks.h"
65 #include "nat/java_lang_VMClass.h"
66 #include "nat/java_lang_Throwable.h"
67
68 /* Include files for IO functions */
69
70 #include <fcntl.h>
71 #include <dirent.h>
72 #include <sys/types.h>
73 #ifdef _OSF_SOURCE 
74 #include <sys/mode.h>
75 #endif
76 #include <sys/stat.h>
77
78 #include "threads/threadio.h"
79
80 /* include table of native functions */
81
82 #include "nativetable.inc"
83
84
85 /* for java-string to char conversion */
86 #define MAXSTRINGSIZE 1000                          
87
88
89 /******************** systemclasses required for native methods ***************/
90
91 classinfo *class_java_lang_Class;
92 classinfo *class_java_lang_VMClass;
93 classinfo *class_java_lang_System;
94 classinfo *class_java_lang_ClassLoader;
95 classinfo *class_gnu_java_lang_SystemClassLoader;
96 classinfo *class_java_lang_SecurityManager;
97 classinfo *class_java_lang_Double;
98 classinfo *class_java_lang_Float;
99 classinfo *class_java_lang_Long;
100 classinfo *class_java_lang_Byte;
101 classinfo *class_java_lang_Short;
102 classinfo *class_java_lang_Boolean;
103 classinfo *class_java_lang_Void;
104 classinfo *class_java_lang_Character;
105 classinfo *class_java_lang_Integer;
106
107 methodinfo *method_vmclass_init;
108
109
110 /* the system classloader object */
111 struct java_lang_ClassLoader *SystemClassLoader = NULL;
112
113 /* for raising exceptions from native methods */
114 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
115 java_objectheader* _exceptionptr = NULL;
116 #endif
117
118 /************* use classinfo structure as java.lang.Class object **************/
119
120 void use_class_as_object(classinfo *c) 
121 {
122         if (!c->classvftbl) {
123                 c->header.vftbl = class_java_lang_Class->vftbl;
124                 c->classvftbl = true;
125         }
126              
127 }
128
129
130 /*************************** include native methods ***************************/ 
131
132 #ifdef USE_GTK 
133 #include "nat/GdkGraphics.c"
134 #include "nat/GtkComponentPeer.c"
135 #include "nat/GdkPixbufDecoder.c"
136 #include "nat/GtkScrollPanePeer.c"
137 #include "nat/GtkFileDialogPeer.c"
138 #endif
139
140
141 /************************** tables for methods ********************************/
142
143 #undef JOWENN_DEBUG
144 #undef JOWENN_DEBUG1
145
146 #ifdef STATIC_CLASSPATH
147 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
148
149 /* table for fast string comparison */
150 static nativecompref nativecomptable[NATIVETABLESIZE];
151
152 /* string comparsion table initialized */
153 static bool nativecompdone = false;
154 #endif
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 (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 (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 (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 (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         classinfo *c;
878     u4 key;
879     u4 slot;
880     u2 i;
881
882 //#define DEBUG_LITERALSTRING_U2
883 #ifdef DEBUG_LITERALSTRING_U2
884     printf("literalstring_u2: length=%d, offset=%d\n", length, offset);
885         fflush(stdout);
886 #endif
887     
888     /* find location in hashtable */
889     key  = unicode_hashkey(a->data + offset, length);
890     slot = key & (string_hash.size - 1);
891     s    = string_hash.ptr[slot];
892
893     while (s) {
894                 js = (java_lang_String *) s->string;
895
896                 if (length == js->count) {
897                         /* compare text */
898                         for (i = 0; i < length; i++) {
899                                 if (a->data[offset + i] != js->value->data[i])
900                                         goto nomatch;
901                         }
902
903                         /* string already in hashtable, free memory */
904                         if (!copymode)
905                                 mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
906
907 #ifdef DEBUG_LITERALSTRING_U2
908                         printf("literalstring_u2: foundentry at %p\n", js);
909                         utf_display(javastring_toutf(js, 0));
910                         printf("\n\n");
911                         fflush(stdout);
912 #endif
913                         return (java_objectheader *) js;
914                 }
915
916         nomatch:
917                 /* follow link in external hash chain */
918                 s = s->hashlink;
919     }
920
921     if (copymode) {
922                 /* create copy of u2-array for new javastring */
923                 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
924                 stringdata = mem_alloc(arraysize);
925 /*              memcpy(stringdata, a, arraysize); */
926                 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
927                 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
928
929     } else {
930                 stringdata = a;
931         }
932
933     /* location in hashtable found, complete arrayheader */
934     stringdata->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
935     stringdata->header.size = length;
936
937         /* if we use eager loading, we have to check loaded String class */
938         if (opt_eager) {
939                 class_java_lang_String =
940                         class_new_intern(utf_new_char("java/lang/String"));
941
942                 if (!class_load(class_java_lang_String))
943                         return NULL;
944
945                 list_addfirst(&unlinkedclasses, class_java_lang_String);
946         }
947
948     /* create new javastring */
949     js = NEW(java_lang_String);
950 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
951         initObjectLock(&js->header);
952 #endif
953         js->header.vftbl = class_java_lang_String->vftbl;
954     js->value  = stringdata;
955     js->offset = 0;
956     js->count  = length;
957
958 #ifdef DEBUG_LITERALSTRING_U2
959         printf("literalstring_u2: newly created at %p\n", js);
960         utf_display(javastring_toutf(js, 0));
961         printf("\n\n");
962         fflush(stdout);
963 #endif
964                         
965     /* create new literalstring */
966     s = NEW(literalstring);
967     s->hashlink = string_hash.ptr[slot];
968     s->string   = (java_objectheader *) js;
969     string_hash.ptr[slot] = s;
970
971     /* update number of hashtable entries */
972     string_hash.entries++;
973
974     /* reorganization of hashtable */       
975     if (string_hash.entries > (string_hash.size * 2)) {
976                 /* reorganization of hashtable, average length of 
977          the external chains is approx. 2                */  
978
979                 u4 i;
980                 literalstring *s;
981                 hashtable newhash; /* the new hashtable */
982       
983                 /* create new hashtable, double the size */
984                 init_hashtable(&newhash, string_hash.size * 2);
985                 newhash.entries = string_hash.entries;
986       
987                 /* transfer elements to new hashtable */
988                 for (i = 0; i < string_hash.size; i++) {
989                         s = string_hash.ptr[i];
990                         while (s) {
991                                 literalstring *nexts = s->hashlink;
992                                 js   = (java_lang_String *) s->string;
993                                 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
994           
995                                 s->hashlink = newhash.ptr[slot];
996                                 newhash.ptr[slot] = s;
997         
998                                 /* follow link in external hash chain */  
999                                 s = nexts;
1000                         }
1001                 }
1002         
1003                 /* dispose old table */ 
1004                 MFREE(string_hash.ptr, void*, string_hash.size);
1005                 string_hash = newhash;
1006     }
1007
1008     return (java_objectheader *) js;
1009 }
1010
1011
1012 /******************** Function: literalstring_new *****************************
1013
1014     creates a new javastring with the text of the utf-symbol
1015     and inserts it into the string hashtable
1016
1017 *******************************************************************************/
1018
1019 java_objectheader *literalstring_new(utf *u)
1020 {
1021     char *utf_ptr = u->text;         /* pointer to current unicode character in utf string */
1022     u4 utflength  = utf_strlen(u);   /* length of utf-string if uncompressed */
1023     java_chararray *a;               /* u2-array constructed from utf string */
1024     u4 i;
1025
1026     /* allocate memory */ 
1027     a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
1028
1029     /* convert utf-string to u2-array */
1030     for (i = 0; i < utflength; i++)
1031                 a->data[i] = utf_nextu2(&utf_ptr);
1032
1033     return literalstring_u2(a, utflength, 0, false);
1034 }
1035
1036
1037 /********************** function: literalstring_free **************************
1038
1039         removes a javastring from memory                       
1040
1041 ******************************************************************************/
1042
1043 void literalstring_free(java_objectheader* sobj)
1044 {
1045         java_lang_String *s = (java_lang_String *) sobj;
1046         java_chararray *a = s->value;
1047
1048         /* dispose memory of java.lang.String object */
1049         FREE(s, java_lang_String);
1050
1051         /* dispose memory of java-characterarray */
1052         FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
1053 }
1054
1055
1056 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
1057 {
1058     *dest = src;
1059 #if 0
1060     /* XXX this kind of copying does not work (in the general
1061      * case). The interface tables would have to be copied, too. I
1062      * don't see why we should make a copy anyway. -Edwin
1063      */
1064         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1065         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1066         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1067 #endif
1068 }
1069
1070
1071 /******************************************************************************************                                                                                                             
1072
1073         creates method signature (excluding return type) from array of 
1074         class-objects representing the parameters of the method 
1075
1076 *******************************************************************************************/
1077
1078
1079 utf *create_methodsig(java_objectarray* types, char *retType)
1080 {
1081     char *buffer;       /* buffer for building the desciptor */
1082     char *pos;          /* current position in buffer */
1083     utf *result;        /* the method signature */
1084     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1085     u4 i, j;
1086  
1087     if (!types) return NULL;
1088
1089     /* determine required buffer-size */    
1090     for (i = 0; i < types->header.size; i++) {
1091                 classinfo *c = (classinfo *) types->data[i];
1092                 buffer_size  = buffer_size + c->name->blength + 2;
1093     }
1094
1095     if (retType) buffer_size += strlen(retType);
1096
1097     /* allocate buffer */
1098     buffer = MNEW(u1, buffer_size);
1099     pos    = buffer;
1100     
1101     /* method-desciptor starts with parenthesis */
1102     *pos++ = '(';
1103
1104     for (i = 0; i < types->header.size; i++) {
1105                 char ch;           
1106
1107                 /* current argument */
1108             classinfo *c = (classinfo *) types->data[i];
1109
1110             /* current position in utf-text */
1111             char *utf_ptr = c->name->text; 
1112             
1113             /* determine type of argument */
1114             if ((ch = utf_nextu2(&utf_ptr)) == '[') {
1115                 /* arrayclass */
1116                 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1117                                 *pos++ = *utf_ptr; /* copy text */
1118                         }
1119
1120             } else {            
1121                         /* check for primitive types */
1122                         for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1123                                 char *utf_pos   = utf_ptr - 1;
1124                                 char *primitive = primitivetype_table[j].wrapname;
1125
1126                                 /* compare text */
1127                                 while (utf_pos < utf_end(c->name)) {
1128                                         if (*utf_pos++ != *primitive++) goto nomatch;
1129                                 }
1130
1131                                 /* primitive type found */
1132                                 *pos++ = primitivetype_table[j].typesig;
1133                                 goto next_type;
1134
1135                         nomatch:
1136                                 ;
1137                         }
1138
1139                         /* no primitive type and no arrayclass, so must be object */
1140                         *pos++ = 'L';
1141
1142                         /* copy text */
1143                         for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1144                                 *pos++ = *utf_ptr;
1145                         }
1146
1147                         *pos++ = ';';
1148
1149                 next_type:
1150                         ;
1151                 }  
1152     }       
1153
1154     *pos++ = ')';
1155
1156     if (retType) {
1157                 for (i = 0; i < strlen(retType); i++) {
1158                         *pos++ = retType[i];
1159                 }
1160     }
1161
1162     /* create utf-string */
1163     result = utf_new(buffer, (pos - buffer));
1164     MFREE(buffer, u1, buffer_size);
1165
1166     return result;
1167 }
1168
1169
1170 /******************************************************************************************
1171
1172         retrieve the next argument or returntype from a descriptor
1173         and return the corresponding class 
1174
1175 *******************************************************************************************/
1176
1177 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1178 {
1179     classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1180                                          (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1181     if (!c)
1182         /* unknown type */
1183         panic("illegal descriptor");
1184
1185     if (skip) return NULL;
1186
1187     use_class_as_object(c);
1188     return c;
1189 }
1190
1191
1192 /* get_parametertypes **********************************************************
1193
1194    use the descriptor of a method to generate a java/lang/Class array
1195    which contains the classes of the parametertypes of the method
1196
1197 *******************************************************************************/
1198
1199 java_objectarray* get_parametertypes(methodinfo *m) 
1200 {
1201     utf  *descr    =  m->descriptor;    /* method-descriptor */ 
1202     char *utf_ptr  =  descr->text;      /* current position in utf-text */
1203     char *desc_end =  utf_end(descr);   /* points behind utf string     */
1204     java_objectarray* result;
1205     int parametercount = 0;
1206     int i;
1207
1208     /* skip '(' */
1209     utf_nextu2(&utf_ptr);
1210   
1211     /* determine number of parameters */
1212     while (*utf_ptr != ')') {
1213         get_type(&utf_ptr, desc_end, true);
1214                 parametercount++;
1215     }
1216
1217     /* create class-array */
1218     result = builtin_anewarray(parametercount, class_java_lang_Class);
1219
1220     utf_ptr = descr->text;
1221     utf_nextu2(&utf_ptr);
1222
1223     /* get returntype classes */
1224     for (i = 0; i < parametercount; i++)
1225             result->data[i] =
1226                         (java_objectheader *) get_type(&utf_ptr, desc_end, false);
1227
1228     return result;
1229 }
1230
1231
1232 /* get_exceptiontypes **********************************************************
1233
1234    get the exceptions which can be thrown by a method
1235
1236 *******************************************************************************/
1237
1238 java_objectarray* get_exceptiontypes(methodinfo *m) {
1239     u2 exccount=m->thrownexceptionscount;
1240     u2 i;
1241     java_objectarray *result;
1242     /* create class-array */
1243     result = builtin_anewarray(exccount, class_java_lang_Class);
1244     for (i=0;i<exccount;i++) {
1245         java_objectheader *oh=(java_objectheader*)(m->thrownexceptions[i]);
1246         use_class_as_object(oh);
1247         result->data[i]=oh;
1248     }
1249     return result;
1250 }
1251
1252
1253
1254
1255
1256 /******************************************************************************************
1257
1258         get the returntype class of a method
1259
1260 *******************************************************************************************/
1261
1262 classinfo *get_returntype(methodinfo *m) 
1263 {
1264         char *utf_ptr;   /* current position in utf-text */
1265         char *desc_end;  /* points behind utf string     */
1266         utf *desc = m->descriptor; /* method-descriptor  */
1267
1268         utf_ptr  = desc->text;
1269         desc_end = utf_end(desc);
1270
1271         /* ignore parametertypes */
1272         while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1273                 /* skip */ ;
1274
1275         return get_type(&utf_ptr,desc_end, false);
1276 }
1277
1278
1279 /*****************************************************************************/
1280 /*****************************************************************************/
1281
1282
1283 /*--------------------------------------------------------*/
1284 void printNativeCall(nativeCall nc) {
1285   int i,j;
1286
1287   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1288   for (i=0; i<nc.methCnt; i++) {  
1289       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1290
1291     for (j=0; j<nc.callCnt[i]; j++) {  
1292         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1293         nc.methods[i].methodCalls[j].classname, 
1294         nc.methods[i].methodCalls[j].methodname, 
1295         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1296       }
1297     }
1298   printf("-+++++--------------------\n");fflush(stdout);
1299 }
1300
1301 /*--------------------------------------------------------*/
1302 void printCompNativeCall(nativeCompCall nc) {
1303   int i,j;
1304   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
1305   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1306   utf_display(nc.classname); fflush(stdout);
1307   
1308   for (i=0; i<nc.methCnt; i++) {  
1309     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1310     utf_display(nc.methods[i].methodname); fflush(stdout);
1311     utf_display(nc.methods[i].descriptor);fflush(stdout);
1312     printf("\n");fflush(stdout);
1313
1314     for (j=0; j<nc.callCnt[i]; j++) {  
1315       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1316         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1317         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1318         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1319         printf("\n");fflush(stdout);
1320       }
1321     }
1322 printf("---------------------\n");fflush(stdout);
1323 }
1324
1325
1326 /*--------------------------------------------------------*/
1327 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1328 {
1329     int i = 0;
1330     int j = 0;
1331     int cnt = 0;
1332     classMeth mc;
1333     mc.i_class = i;
1334     mc.j_method = j;
1335     mc.methCnt = cnt;
1336
1337     return mc;
1338 }
1339
1340 /*--------------------------------------------------------*/
1341 nativeCall* findNativeClassCalls(char *aclassname ) {
1342 int i;
1343
1344 for (i=0;i<NATIVECALLSSIZE; i++) {
1345    /* convert table to utf later to speed up search */ 
1346    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1347         return &nativeCalls[i];
1348    }
1349
1350 return NULL;
1351 }
1352 /*--------------------------------------------------------*/
1353 /*--------------------------------------------------------*/
1354 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1355   int i,j;
1356
1357
1358   ncc->classname = utf_new_char(nc.classname); 
1359   ncc->methCnt = nc.methCnt;
1360   
1361   for (i=0; i<nc.methCnt; i++) {  
1362     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1363     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1364     ncc->callCnt[i] = nc.callCnt[i];
1365
1366     for (j=0; j<nc.callCnt[i]; j++) {  
1367
1368         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1369
1370         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1371           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1372           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1373           }
1374         else {
1375           ncc->methods[i].methodCalls[j].methodname = NULL;
1376           ncc->methods[i].methodCalls[j].descriptor = NULL;
1377           }
1378       }
1379     }
1380 }
1381
1382
1383
1384 /*--------------------------------------------------------*/
1385
1386 bool natcall2utf(bool natcallcompdone) {
1387 int i;
1388
1389 if (natcallcompdone) 
1390         return true;
1391
1392 for (i=0;i<NATIVECALLSSIZE; i++) {
1393    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1394    }
1395
1396 return true;
1397 }
1398
1399 /*--------------------------------------------------------*/
1400
1401
1402 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end,classinfo **start)
1403 {
1404 #if defined(__GNUC__)
1405 #warning platform dependend
1406 #endif
1407         java_objectarray *tmpArray;
1408         int i;
1409         classinfo **current;
1410         classinfo *c;
1411         size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1412         /*printf("end %p, start %p, size %ld\n",end,start,size);*/
1413         if (!class_java_lang_Class)
1414                 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
1415         if (!class_java_lang_SecurityManager)
1416                 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1417         if (size>0) {
1418                 if (start==class_java_lang_SecurityManager) {
1419                         size--;
1420                         start--;
1421                 }
1422         }
1423         tmpArray=builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
1424
1425         for(i=0,current=start;i<size;i++,current--) {
1426                 c=*current;
1427 /*              printf("%d\n",i);
1428                 utf_display(c->name);*/
1429                 use_class_as_object(c);
1430                 tmpArray->data[i]=c;
1431         }
1432         return tmpArray;
1433
1434 }
1435
1436 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end,classinfo **start)
1437 {
1438 #if defined(__GNUC__)
1439 #warning platform dependend
1440 #endif
1441         int i;
1442         classinfo **current;
1443         classinfo *c;
1444         classinfo *privilegedAction;
1445         size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1446 /*      log_text("builtin_asm_getclassloader");
1447         printf("end %p, start %p, size %ld\n",end,start,size);*/
1448
1449         if (!class_java_lang_SecurityManager)
1450                 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1451         if (size>0) {
1452                 if (start==class_java_lang_SecurityManager) {
1453                         size--;
1454                         start--;
1455                 }
1456         }
1457
1458         privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
1459
1460         for(i=0,current=start;i<size;i++,current--) {
1461                 c=*current;
1462                 if (c==privilegedAction) return NULL;
1463                 if (c->classloader) return c->classloader;
1464         }
1465         return NULL;
1466
1467
1468
1469
1470 /*
1471         log_text("Java_java_lang_VMSecurityManager_currentClassLoader");
1472         init_systemclassloader();
1473
1474         return SystemClassLoader;*/
1475 }
1476
1477 /*
1478  * These are local overrides for various environment variables in Emacs.
1479  * Please do not remove this and leave it at the end of the file, where
1480  * Emacs will automagically detect them.
1481  * ---------------------------------------------------------------------
1482  * Local variables:
1483  * mode: c
1484  * indent-tabs-mode: t
1485  * c-basic-offset: 4
1486  * tab-width: 4
1487  * End:
1488  */