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