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