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