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