x86_64 section
[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 1361 2004-07-28 10:51:14Z twisti $
35
36 */
37
38
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <time.h>
42 #include <math.h>
43 #include <string.h>
44 #include <assert.h>
45 #include <sys/time.h>
46 #include <utime.h>
47
48 #include "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         js->header.vftbl = class_java_lang_String->vftbl;
930     js->value  = stringdata;
931     js->offset = 0;
932     js->count  = length;
933
934 #ifdef DEBUG_LITERALSTRING_U2
935         printf("literalstring_u2: newly created at %p\n", js);
936         utf_display(javastring_toutf(js, 0));
937         printf("\n\n");
938         fflush(stdout);
939 #endif
940                         
941     /* create new literalstring */
942     s = NEW(literalstring);
943     s->hashlink = string_hash.ptr[slot];
944     s->string   = (java_objectheader *) js;
945     string_hash.ptr[slot] = s;
946
947     /* update number of hashtable entries */
948     string_hash.entries++;
949
950     /* reorganization of hashtable */       
951     if (string_hash.entries > (string_hash.size * 2)) {
952                 /* reorganization of hashtable, average length of 
953          the external chains is approx. 2                */  
954
955                 u4 i;
956                 literalstring *s;
957                 hashtable newhash; /* the new hashtable */
958       
959                 /* create new hashtable, double the size */
960                 init_hashtable(&newhash, string_hash.size * 2);
961                 newhash.entries = string_hash.entries;
962       
963                 /* transfer elements to new hashtable */
964                 for (i = 0; i < string_hash.size; i++) {
965                         s = string_hash.ptr[i];
966                         while (s) {
967                                 literalstring *nexts = s->hashlink;
968                                 js   = (java_lang_String *) s->string;
969                                 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
970           
971                                 s->hashlink = newhash.ptr[slot];
972                                 newhash.ptr[slot] = s;
973         
974                                 /* follow link in external hash chain */  
975                                 s = nexts;
976                         }
977                 }
978         
979                 /* dispose old table */ 
980                 MFREE(string_hash.ptr, void*, string_hash.size);
981                 string_hash = newhash;
982     }
983
984     return (java_objectheader *) js;
985 }
986
987
988 /******************** Function: literalstring_new *****************************
989
990     creates a new javastring with the text of the utf-symbol
991     and inserts it into the string hashtable
992
993 *******************************************************************************/
994
995 java_objectheader *literalstring_new(utf *u)
996 {
997     char *utf_ptr = u->text;         /* pointer to current unicode character in utf string */
998     u4 utflength  = utf_strlen(u);   /* length of utf-string if uncompressed */
999     java_chararray *a;               /* u2-array constructed from utf string */
1000     u4 i;
1001
1002     /* allocate memory */ 
1003     a = lit_mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
1004
1005     /* convert utf-string to u2-array */
1006     for (i = 0; i < utflength; i++)
1007                 a->data[i] = utf_nextu2(&utf_ptr);
1008
1009     return literalstring_u2(a, utflength, 0, false);
1010 }
1011
1012
1013 /********************** function: literalstring_free **************************
1014
1015         removes a javastring from memory                       
1016
1017 ******************************************************************************/
1018
1019 void literalstring_free(java_objectheader* sobj)
1020 {
1021         java_lang_String *s = (java_lang_String *) sobj;
1022         java_chararray *a = s->value;
1023
1024         /* dispose memory of java.lang.String object */
1025         LFREE(s, java_lang_String);
1026
1027         /* dispose memory of java-characterarray */
1028         LFREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
1029 }
1030
1031
1032 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
1033 {
1034     *dest = src;
1035 #if 0
1036     /* XXX this kind of copying does not work (in the general
1037      * case). The interface tables would have to be copied, too. I
1038      * don't see why we should make a copy anyway. -Edwin
1039      */
1040         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1041         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1042         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1043 #endif
1044 }
1045
1046
1047 /******************************************************************************************                                                                                                             
1048
1049         creates method signature (excluding return type) from array of 
1050         class-objects representing the parameters of the method 
1051
1052 *******************************************************************************************/
1053
1054
1055 utf *create_methodsig(java_objectarray* types, char *retType)
1056 {
1057     char *buffer;       /* buffer for building the desciptor */
1058     char *pos;          /* current position in buffer */
1059     utf *result;        /* the method signature */
1060     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1061     u4 i, j;
1062  
1063     if (!types) return NULL;
1064
1065     /* determine required buffer-size */    
1066     for (i = 0; i < types->header.size; i++) {
1067                 classinfo *c = (classinfo *) types->data[i];
1068                 buffer_size  = buffer_size + c->name->blength + 2;
1069     }
1070
1071     if (retType) buffer_size += strlen(retType);
1072
1073     /* allocate buffer */
1074     buffer = MNEW(u1, buffer_size);
1075     pos    = buffer;
1076     
1077     /* method-desciptor starts with parenthesis */
1078     *pos++ = '(';
1079
1080     for (i = 0; i < types->header.size; i++) {
1081                 char ch;           
1082
1083                 /* current argument */
1084             classinfo *c = (classinfo *) types->data[i];
1085
1086             /* current position in utf-text */
1087             char *utf_ptr = c->name->text; 
1088             
1089             /* determine type of argument */
1090             if ((ch = utf_nextu2(&utf_ptr)) == '[') {
1091                 /* arrayclass */
1092                 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1093                                 *pos++ = *utf_ptr; /* copy text */
1094                         }
1095
1096             } else {            
1097                         /* check for primitive types */
1098                         for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1099                                 char *utf_pos   = utf_ptr - 1;
1100                                 char *primitive = primitivetype_table[j].wrapname;
1101
1102                                 /* compare text */
1103                                 while (utf_pos < utf_end(c->name)) {
1104                                         if (*utf_pos++ != *primitive++) goto nomatch;
1105                                 }
1106
1107                                 /* primitive type found */
1108                                 *pos++ = primitivetype_table[j].typesig;
1109                                 goto next_type;
1110
1111                         nomatch:
1112                                 ;
1113                         }
1114
1115                         /* no primitive type and no arrayclass, so must be object */
1116                         *pos++ = 'L';
1117
1118                         /* copy text */
1119                         for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1120                                 *pos++ = *utf_ptr;
1121                         }
1122
1123                         *pos++ = ';';
1124
1125                 next_type:
1126                         ;
1127                 }  
1128     }       
1129
1130     *pos++ = ')';
1131
1132     if (retType) {
1133                 for (i = 0; i < strlen(retType); i++) {
1134                         *pos++ = retType[i];
1135                 }
1136     }
1137
1138     /* create utf-string */
1139     result = utf_new(buffer, (pos - buffer));
1140     MFREE(buffer, u1, buffer_size);
1141
1142     return result;
1143 }
1144
1145
1146 /******************************************************************************************
1147
1148         retrieve the next argument or returntype from a descriptor
1149         and return the corresponding class 
1150
1151 *******************************************************************************************/
1152
1153 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1154 {
1155     classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1156                                          (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1157     if (!c)
1158         /* unknown type */
1159         panic("illegal descriptor");
1160
1161     if (skip) return NULL;
1162
1163     use_class_as_object(c);
1164     return c;
1165 }
1166
1167
1168 /* get_parametertypes **********************************************************
1169
1170    use the descriptor of a method to generate a java/lang/Class array
1171    which contains the classes of the parametertypes of the method
1172
1173 *******************************************************************************/
1174
1175 java_objectarray* get_parametertypes(methodinfo *m) 
1176 {
1177     utf  *descr    =  m->descriptor;    /* method-descriptor */ 
1178     char *utf_ptr  =  descr->text;      /* current position in utf-text */
1179     char *desc_end =  utf_end(descr);   /* points behind utf string     */
1180     java_objectarray* result;
1181     int parametercount = 0;
1182     int i;
1183
1184     /* skip '(' */
1185     utf_nextu2(&utf_ptr);
1186   
1187     /* determine number of parameters */
1188     while (*utf_ptr != ')') {
1189         get_type(&utf_ptr, desc_end, true);
1190                 parametercount++;
1191     }
1192
1193     /* create class-array */
1194     result = builtin_anewarray(parametercount, class_java_lang_Class);
1195
1196     utf_ptr = descr->text;
1197     utf_nextu2(&utf_ptr);
1198
1199     /* get returntype classes */
1200     for (i = 0; i < parametercount; i++)
1201             result->data[i] =
1202                         (java_objectheader *) get_type(&utf_ptr, desc_end, false);
1203
1204     return result;
1205 }
1206
1207
1208 /* get_exceptiontypes **********************************************************
1209
1210    get the exceptions which can be thrown by a method
1211
1212 *******************************************************************************/
1213
1214 java_objectarray* get_exceptiontypes(methodinfo *m) {
1215     u2 exccount=m->thrownexceptionscount;
1216     u2 i;
1217     java_objectarray *result;
1218     /* create class-array */
1219     result = builtin_anewarray(exccount, class_java_lang_Class);
1220     for (i=0;i<exccount;i++) {
1221         java_objectheader *oh=(java_objectheader*)(m->thrownexceptions[i]);
1222         use_class_as_object(oh);
1223         result->data[i]=oh;
1224     }
1225     return result;
1226 }
1227
1228
1229
1230
1231
1232 /******************************************************************************************
1233
1234         get the returntype class of a method
1235
1236 *******************************************************************************************/
1237
1238 classinfo *get_returntype(methodinfo *m) 
1239 {
1240         char *utf_ptr;   /* current position in utf-text */
1241         char *desc_end;  /* points behind utf string     */
1242         utf *desc = m->descriptor; /* method-descriptor  */
1243
1244         utf_ptr  = desc->text;
1245         desc_end = utf_end(desc);
1246
1247         /* ignore parametertypes */
1248         while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1249                 /* skip */ ;
1250
1251         return get_type(&utf_ptr,desc_end, false);
1252 }
1253
1254
1255 /*****************************************************************************/
1256 /*****************************************************************************/
1257
1258
1259 /*--------------------------------------------------------*/
1260 void printNativeCall(nativeCall nc) {
1261   int i,j;
1262
1263   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1264   for (i=0; i<nc.methCnt; i++) {  
1265       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1266
1267     for (j=0; j<nc.callCnt[i]; j++) {  
1268         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1269         nc.methods[i].methodCalls[j].classname, 
1270         nc.methods[i].methodCalls[j].methodname, 
1271         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1272       }
1273     }
1274   printf("-+++++--------------------\n");fflush(stdout);
1275 }
1276
1277 /*--------------------------------------------------------*/
1278 void printCompNativeCall(nativeCompCall nc) {
1279   int i,j;
1280   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
1281   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1282   utf_display(nc.classname); fflush(stdout);
1283   
1284   for (i=0; i<nc.methCnt; i++) {  
1285     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1286     utf_display(nc.methods[i].methodname); fflush(stdout);
1287     utf_display(nc.methods[i].descriptor);fflush(stdout);
1288     printf("\n");fflush(stdout);
1289
1290     for (j=0; j<nc.callCnt[i]; j++) {  
1291       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1292         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1293         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1294         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1295         printf("\n");fflush(stdout);
1296       }
1297     }
1298 printf("---------------------\n");fflush(stdout);
1299 }
1300
1301
1302 /*--------------------------------------------------------*/
1303 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1304 {
1305     int i = 0;
1306     int j = 0;
1307     int cnt = 0;
1308     classMeth mc;
1309     mc.i_class = i;
1310     mc.j_method = j;
1311     mc.methCnt = cnt;
1312
1313     return mc;
1314 }
1315
1316 /*--------------------------------------------------------*/
1317 nativeCall* findNativeClassCalls(char *aclassname ) {
1318 int i;
1319
1320 for (i=0;i<NATIVECALLSSIZE; i++) {
1321    /* convert table to utf later to speed up search */ 
1322    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1323         return &nativeCalls[i];
1324    }
1325
1326 return NULL;
1327 }
1328 /*--------------------------------------------------------*/
1329 /*--------------------------------------------------------*/
1330 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1331   int i,j;
1332
1333
1334   ncc->classname = utf_new_char(nc.classname); 
1335   ncc->methCnt = nc.methCnt;
1336   
1337   for (i=0; i<nc.methCnt; i++) {  
1338     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1339     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1340     ncc->callCnt[i] = nc.callCnt[i];
1341
1342     for (j=0; j<nc.callCnt[i]; j++) {  
1343
1344         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1345
1346         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1347           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1348           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1349           }
1350         else {
1351           ncc->methods[i].methodCalls[j].methodname = NULL;
1352           ncc->methods[i].methodCalls[j].descriptor = NULL;
1353           }
1354       }
1355     }
1356 }
1357
1358
1359
1360 /*--------------------------------------------------------*/
1361
1362 bool natcall2utf(bool natcallcompdone) {
1363 int i;
1364
1365 if (natcallcompdone) 
1366         return true;
1367
1368 for (i=0;i<NATIVECALLSSIZE; i++) {
1369    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1370    }
1371
1372 return true;
1373 }
1374
1375 /*--------------------------------------------------------*/
1376
1377
1378 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end,classinfo **start)
1379 {
1380 #if defined(__GNUC__)
1381 #warning platform dependend
1382 #endif
1383         java_objectarray *tmpArray;
1384         int i;
1385         classinfo **current;
1386         classinfo *c;
1387         size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1388         /*printf("end %p, start %p, size %ld\n",end,start,size);*/
1389         if (!class_java_lang_Class)
1390                 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
1391         if (!class_java_lang_SecurityManager)
1392                 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1393         if (size>0) {
1394                 if (start==class_java_lang_SecurityManager) {
1395                         size--;
1396                         start--;
1397                 }
1398         }
1399         tmpArray=builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
1400
1401         for(i=0,current=start;i<size;i++,current--) {
1402                 c=*current;
1403 /*              printf("%d\n",i);
1404                 utf_display(c->name);*/
1405                 use_class_as_object(c);
1406                 tmpArray->data[i]=c;
1407         }
1408         return tmpArray;
1409
1410 }
1411
1412 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end,classinfo **start)
1413 {
1414 #if defined(__GNUC__)
1415 #warning platform dependend
1416 #endif
1417         int i;
1418         classinfo **current;
1419         classinfo *c;
1420         classinfo *privilegedAction;
1421         size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1422 /*      log_text("builtin_asm_getclassloader");
1423         printf("end %p, start %p, size %ld\n",end,start,size);*/
1424
1425         if (!class_java_lang_SecurityManager)
1426                 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1427         if (size>0) {
1428                 if (start==class_java_lang_SecurityManager) {
1429                         size--;
1430                         start--;
1431                 }
1432         }
1433
1434         privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
1435
1436         for(i=0,current=start;i<size;i++,current--) {
1437                 c=*current;
1438                 if (c==privilegedAction) return NULL;
1439                 if (c->classloader) return c->classloader;
1440         }
1441         return NULL;
1442
1443
1444
1445
1446 /*
1447         log_text("Java_java_lang_VMSecurityManager_currentClassLoader");
1448         init_systemclassloader();
1449
1450         return SystemClassLoader;*/
1451 }
1452
1453 /*
1454  * These are local overrides for various environment variables in Emacs.
1455  * Please do not remove this and leave it at the end of the file, where
1456  * Emacs will automagically detect them.
1457  * ---------------------------------------------------------------------
1458  * Local variables:
1459  * mode: c
1460  * indent-tabs-mode: t
1461  * c-basic-offset: 4
1462  * tab-width: 4
1463  * End:
1464  */