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