* libarch_la_SOURCES: Removed symcat.h.
[cacao.git] / src / native / native.c
1 /* src/native/native.c - table of native functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
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    Changes: Christian Thalinger
32
33    $Id: native.c 3828 2005-12-01 19:46:05Z twisti $
34
35 */
36
37
38 #include <assert.h>
39
40 #include "config.h"
41 #include "vm/types.h"
42
43 #include "cacao/cacao.h"
44 #include "mm/memory.h"
45 #include "native/jni.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_Throwable.h"
48 #include "toolbox/logging.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
52 #include "vm/hashtable.h"
53 #include "vm/loader.h"
54 #include "vm/options.h"
55 #include "vm/resolve.h"
56 #include "vm/stringlocal.h"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/jit.h"
59
60 #if !defined(ENABLE_STATICVM)
61 # include "libltdl/ltdl.h"
62 #endif
63
64
65 /* include table of native functions ******************************************/
66
67 #include "native/include/java_lang_Cloneable.h"
68 #include "native/include/java_util_Properties.h"
69 #include "native/include/java_io_InputStream.h"
70 #include "native/include/java_io_PrintStream.h"
71
72 #include "native/include/gnu_classpath_VMStackWalker.h"
73 #include "native/include/gnu_classpath_VMSystemProperties.h"
74 #include "native/include/java_lang_Class.h"
75 #include "native/include/java_lang_Object.h"
76 #include "native/include/java_lang_VMClass.h"
77 #include "native/include/java_lang_VMClassLoader.h"
78 #include "native/include/java_lang_VMObject.h"
79 #include "native/include/java_lang_VMRuntime.h"
80 #include "native/include/java_lang_VMString.h"
81 #include "native/include/java_lang_VMSystem.h"
82 #include "native/include/java_lang_VMThread.h"
83 #include "native/include/java_lang_VMThrowable.h"
84 #include "native/include/java_lang_reflect_Constructor.h"
85 #include "native/include/java_lang_reflect_Field.h"
86 #include "native/include/java_lang_reflect_Method.h"
87 #include "native/include/java_lang_reflect_VMProxy.h"
88 #include "native/include/java_security_VMAccessController.h"
89
90 #if defined(ENABLE_STATICVM)
91
92 /* these are required to prevent compiler warnings */
93
94 #include "native/include/java_net_DatagramPacket.h"
95 #include "native/include/java_net_InetAddress.h"
96 #include "native/include/java_net_SocketImpl.h"
97
98 #include "native/include/gnu_java_net_PlainDatagramSocketImpl.h"
99 #include "native/include/gnu_java_net_PlainSocketImpl.h"
100 #include "native/include/gnu_java_nio_PipeImpl.h"
101 #include "native/include/gnu_java_nio_channels_FileChannelImpl.h"
102 #include "native/include/gnu_java_nio_charset_iconv_IconvEncoder.h"
103 #include "native/include/gnu_java_nio_charset_iconv_IconvDecoder.h"
104 #include "native/include/java_lang_VMProcess.h"
105 #include "native/include/java_nio_MappedByteBufferImpl.h"
106 #include "native/include/java_nio_channels_spi_SelectorProvider.h"
107
108 /* now include the native table */
109
110 #include "native/nativetable.inc"
111
112 #else /* defined(ENABLE_STATICVM) */
113
114 /* Ensure that symbols for functions implemented within CACAO are used and    */
115 /* exported to dlopen.                                                        */
116
117 static functionptr dummynativetable[] = {
118         (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext,
119
120         (functionptr) Java_gnu_classpath_VMSystemProperties_preInit,
121
122         (functionptr) Java_java_lang_VMClass_isInstance,
123         (functionptr) Java_java_lang_VMClass_isAssignableFrom,
124         (functionptr) Java_java_lang_VMClass_isInterface,
125         (functionptr) Java_java_lang_VMClass_isPrimitive,
126         (functionptr) Java_java_lang_VMClass_getName,
127         (functionptr) Java_java_lang_VMClass_getSuperclass,
128         (functionptr) Java_java_lang_VMClass_getInterfaces,
129         (functionptr) Java_java_lang_VMClass_getComponentType,
130         (functionptr) Java_java_lang_VMClass_getModifiers,
131         (functionptr) Java_java_lang_VMClass_getDeclaringClass,
132         (functionptr) Java_java_lang_VMClass_getDeclaredClasses,
133         (functionptr) Java_java_lang_VMClass_getDeclaredFields,
134         (functionptr) Java_java_lang_VMClass_getDeclaredMethods,
135         (functionptr) Java_java_lang_VMClass_getDeclaredConstructors,
136         (functionptr) Java_java_lang_VMClass_getClassLoader,
137         (functionptr) Java_java_lang_VMClass_forName,
138         (functionptr) Java_java_lang_VMClass_isArray,
139         (functionptr) Java_java_lang_VMClass_throwException,
140
141         (functionptr) Java_java_lang_VMClassLoader_defineClass,
142         (functionptr) Java_java_lang_VMClassLoader_resolveClass,
143         (functionptr) Java_java_lang_VMClassLoader_loadClass,
144         (functionptr) Java_java_lang_VMClassLoader_getPrimitiveClass,
145         (functionptr) Java_java_lang_VMClassLoader_nativeGetResources,
146         (functionptr) Java_java_lang_VMClassLoader_findLoadedClass,
147
148         (functionptr) Java_java_lang_VMObject_getClass,
149         (functionptr) Java_java_lang_VMObject_clone,
150         (functionptr) Java_java_lang_VMObject_notify,
151         (functionptr) Java_java_lang_VMObject_notifyAll,
152         (functionptr) Java_java_lang_VMObject_wait,
153
154         (functionptr) Java_java_lang_VMRuntime_availableProcessors,
155         (functionptr) Java_java_lang_VMRuntime_freeMemory,
156         (functionptr) Java_java_lang_VMRuntime_totalMemory,
157         (functionptr) Java_java_lang_VMRuntime_maxMemory,
158         (functionptr) Java_java_lang_VMRuntime_gc,
159         (functionptr) Java_java_lang_VMRuntime_runFinalization,
160         (functionptr) Java_java_lang_VMRuntime_runFinalizationForExit,
161         (functionptr) Java_java_lang_VMRuntime_traceInstructions,
162         (functionptr) Java_java_lang_VMRuntime_traceMethodCalls,
163         (functionptr) Java_java_lang_VMRuntime_runFinalizersOnExit,
164         (functionptr) Java_java_lang_VMRuntime_exit,
165         (functionptr) Java_java_lang_VMRuntime_nativeLoad,
166         (functionptr) Java_java_lang_VMRuntime_mapLibraryName,
167
168         (functionptr) Java_java_lang_VMString_intern,
169
170         (functionptr) Java_java_lang_VMSystem_arraycopy,
171         (functionptr) Java_java_lang_VMSystem_identityHashCode,
172
173         (functionptr) Java_java_lang_VMThread_start,
174         (functionptr) Java_java_lang_VMThread_interrupt,
175         (functionptr) Java_java_lang_VMThread_isInterrupted,
176         (functionptr) Java_java_lang_VMThread_suspend,
177         (functionptr) Java_java_lang_VMThread_resume,
178         (functionptr) Java_java_lang_VMThread_nativeSetPriority,
179         (functionptr) Java_java_lang_VMThread_nativeStop,
180         (functionptr) Java_java_lang_VMThread_currentThread,
181         (functionptr) Java_java_lang_VMThread_yield,
182         (functionptr) Java_java_lang_VMThread_interrupted,
183         (functionptr) Java_java_lang_VMThread_holdsLock,
184
185         (functionptr) Java_java_lang_VMThrowable_fillInStackTrace,
186         (functionptr) Java_java_lang_VMThrowable_getStackTrace,
187
188         (functionptr) Java_java_lang_reflect_Constructor_getModifiers,
189         (functionptr) Java_java_lang_reflect_Constructor_constructNative,
190
191         (functionptr) Java_java_lang_reflect_Field_getModifiers,
192         (functionptr) Java_java_lang_reflect_Field_getType,
193         (functionptr) Java_java_lang_reflect_Field_get,
194         (functionptr) Java_java_lang_reflect_Field_getBoolean,
195         (functionptr) Java_java_lang_reflect_Field_getByte,
196         (functionptr) Java_java_lang_reflect_Field_getChar,
197         (functionptr) Java_java_lang_reflect_Field_getShort,
198         (functionptr) Java_java_lang_reflect_Field_getInt,
199         (functionptr) Java_java_lang_reflect_Field_getLong,
200         (functionptr) Java_java_lang_reflect_Field_getFloat,
201         (functionptr) Java_java_lang_reflect_Field_getDouble,
202         (functionptr) Java_java_lang_reflect_Field_set,
203         (functionptr) Java_java_lang_reflect_Field_setBoolean,
204         (functionptr) Java_java_lang_reflect_Field_setByte,
205         (functionptr) Java_java_lang_reflect_Field_setChar,
206         (functionptr) Java_java_lang_reflect_Field_setShort,
207         (functionptr) Java_java_lang_reflect_Field_setInt,
208         (functionptr) Java_java_lang_reflect_Field_setLong,
209         (functionptr) Java_java_lang_reflect_Field_setFloat,
210         (functionptr) Java_java_lang_reflect_Field_setDouble,
211
212         (functionptr) Java_java_lang_reflect_Method_getModifiers,
213         (functionptr) Java_java_lang_reflect_Method_getReturnType,
214         (functionptr) Java_java_lang_reflect_Method_getParameterTypes,
215         (functionptr) Java_java_lang_reflect_Method_getExceptionTypes,
216         (functionptr) Java_java_lang_reflect_Method_invokeNative,
217
218         (functionptr) Java_java_lang_reflect_VMProxy_getProxyClass,
219         (functionptr) Java_java_lang_reflect_VMProxy_getProxyData,
220         (functionptr) Java_java_lang_reflect_VMProxy_generateProxyClass,
221
222         (functionptr) Java_java_security_VMAccessController_getStack,
223 };
224
225 #endif /* defined(ENABLE_STATICVM) */
226
227
228 /************************** tables for methods ********************************/
229
230 #undef JOWENN_DEBUG
231 #undef JOWENN_DEBUG1
232
233 #ifdef ENABLE_STATICVM
234 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
235
236 /* table for fast string comparison */
237 static nativecompref nativecomptable[NATIVETABLESIZE];
238
239 /* string comparsion table initialized */
240 static bool nativecompdone = false;
241 #endif
242
243
244 /* XXX don't define this in a header file!!! */
245
246 static struct nativeCall nativeCalls[] =
247 {
248 #include "nativecalls.inc"
249 };
250
251 #define NATIVECALLSSIZE    (sizeof(nativeCalls) / sizeof(struct nativeCall))
252
253 struct nativeCompCall nativeCompCalls[NATIVECALLSSIZE];
254
255
256 /* global variables ***********************************************************/
257
258 #if !defined(ENABLE_STATICVM)
259 static hashtable hashtable_library;
260 static lt_dlhandle mainhandle;
261 #endif
262
263
264 /* native_loadclasses **********************************************************
265
266    Load classes required for native methods.
267
268 *******************************************************************************/
269
270 bool native_init(void)
271 {
272 #if !defined(ENABLE_STATICVM)
273         void *p;
274
275         /* We need to access the dummy native table, not only to remove a warning */
276         /* but to be sure that the table is not optimized away (gcc does this     */
277         /* since 3.4).                                                            */
278
279         p = &dummynativetable;
280
281         /* initialize libltdl */
282
283         if (lt_dlinit()) {
284                 /* XXX how can we throw an exception here? */
285                 log_text(lt_dlerror());
286
287                 return false;
288         }
289
290         /* get the handle for the main program */
291
292         if (!(mainhandle = lt_dlopen(NULL)))
293                 return false;
294
295         /* initialize library hashtable, 10 entries should be enough */
296
297         hashtable_create(&hashtable_library, 10);
298
299 #endif
300
301         /* everything's ok */
302
303         return true;
304 }
305
306
307 /* native_hashtable_library_add ************************************************
308
309    Adds an entry to the native library hashtable.
310
311 *******************************************************************************/
312
313 #if !defined(ENABLE_STATICVM)
314 void native_hashtable_library_add(utf *filename, java_objectheader *loader,
315                                                                   lt_dlhandle handle)
316 {
317         hashtable_library_loader_entry *le;
318         hashtable_library_name_entry   *ne; /* library name                       */
319         u4   key;                           /* hashkey                            */
320         u4   slot;                          /* slot in hashtable                  */
321
322         /* normally addresses are aligned to 4, 8 or 16 bytes */
323
324         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
325         slot = key & (hashtable_library.size - 1);
326         le   = hashtable_library.ptr[slot];
327
328         /* search external hash chain for the entry */
329
330         while (le) {
331                 if (le->loader == loader)
332                         break;
333
334                 le = le->hashlink;                  /* next element in external chain */
335         }
336
337         /* no loader found? create a new entry */
338
339         if (!le) {
340                 le = NEW(hashtable_library_loader_entry);
341
342                 le->loader = loader;
343                 le->namelink = NULL;
344
345                 /* insert entry into hashtable */
346
347                 le->hashlink =
348                         (hashtable_library_loader_entry *) hashtable_library.ptr[slot];
349                 hashtable_library.ptr[slot] = le;
350
351                 /* update number of hashtable-entries */
352
353                 hashtable_library.entries++;
354         }
355
356
357         /* search for library name */
358
359         ne = le->namelink;
360
361         while (ne) {
362                 if (ne->name == filename)
363                         return;
364
365                 ne = ne->hashlink;                  /* next element in external chain */
366         }
367
368         /* not found? add the library name to the classloader */
369
370         ne = NEW(hashtable_library_name_entry);
371
372         ne->name = filename;
373         ne->handle = handle;
374
375         /* insert entry into external chain */
376
377         ne->hashlink = le->namelink;
378         le->namelink = ne;
379 }
380 #endif /* !defined(ENABLE_STATICVM) */
381
382
383 /* native_hashtable_library_find ***********************************************
384
385    Find an entry in the native library hashtable.
386
387 *******************************************************************************/
388
389 #if !defined(ENABLE_STATICVM)
390 hashtable_library_name_entry *native_hashtable_library_find(utf *filename,
391                                                                                                                         java_objectheader *loader)
392 {
393         hashtable_library_loader_entry *le;
394         hashtable_library_name_entry   *ne; /* library name                       */
395         u4   key;                           /* hashkey                            */
396         u4   slot;                          /* slot in hashtable                  */
397
398         /* normally addresses are aligned to 4, 8 or 16 bytes */
399
400         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
401         slot = key & (hashtable_library.size - 1);
402         le   = hashtable_library.ptr[slot];
403
404         /* search external hash chain for the entry */
405
406         while (le) {
407                 if (le->loader == loader)
408                         break;
409
410                 le = le->hashlink;                  /* next element in external chain */
411         }
412
413         /* no loader found? return NULL */
414
415         if (!le)
416                 return NULL;
417
418         /* search for library name */
419
420         ne = le->namelink;
421
422         while (ne) {
423                 if (ne->name == filename)
424                         return ne;
425
426                 ne = ne->hashlink;                  /* next element in external chain */
427         }
428
429         /* return entry, if no entry was found, ne is NULL */
430
431         return ne;
432 }
433 #endif /* !defined(ENABLE_STATICVM) */
434
435
436 /* native_findfunction *********************************************************
437
438    Looks up a method (must have the same class name, method name,
439    descriptor and 'static'ness) and returns a function pointer to it.
440    Returns: function pointer or NULL (if there is no such method)
441
442    Remark: For faster operation, the names/descriptors are converted
443    from C strings to Unicode the first time this function is called.
444
445 *******************************************************************************/
446
447 #if defined(ENABLE_STATICVM)
448 functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
449                                                                 bool isstatic)
450 {
451         /* entry of table for fast string comparison */
452         struct nativecompref *n;
453         s4 i;
454
455         isstatic = isstatic ? true : false;
456         
457         if (!nativecompdone) {
458                 for (i = 0; i < NATIVETABLESIZE; i++) {
459                         nativecomptable[i].classname  = 
460                                 utf_new_char(nativetable[i].classname);
461
462                         nativecomptable[i].methodname = 
463                                 utf_new_char(nativetable[i].methodname);
464
465                         nativecomptable[i].descriptor =
466                                 utf_new_char(nativetable[i].descriptor);
467
468                         nativecomptable[i].isstatic   = nativetable[i].isstatic;
469                         nativecomptable[i].func       = nativetable[i].func;
470                 }
471
472                 nativecompdone = true;
473         }
474
475         for (i = 0; i < NATIVETABLESIZE; i++) {
476                 n = &(nativecomptable[i]);
477
478                 if (cname == n->classname && mname == n->methodname &&
479                     desc == n->descriptor && isstatic == n->isstatic)
480                         return n->func;
481         }
482
483                 
484         /* no function was found, throw exception */
485
486         *exceptionptr =
487                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
488                                                                          mname);
489
490         return NULL;
491 }
492 #endif /* defined(ENABLE_STATICVM) */
493
494
495 /* native_make_overloaded_function *********************************************
496
497    XXX
498
499 *******************************************************************************/
500
501 #if !defined(ENABLE_STATICVM)
502 static char *native_make_overloaded_function(char *name, utf *desc)
503 {
504         char *newname;
505         s4    namelen;
506         char *utf_ptr;
507         u2    c;
508         s4    i;
509
510         utf_ptr = desc->text;
511         namelen = strlen(name) + strlen("__") + strlen("0");
512
513         /* calculate additional length */
514
515         while ((c = utf_nextu2(&utf_ptr)) != ')') {
516                 switch (c) {
517                 case 'Z':
518                 case 'B':
519                 case 'C':
520                 case 'S':
521                 case 'I':
522                 case 'J':
523                 case 'F':
524                 case 'D':
525                         namelen++;
526                         break;
527                 case '[':
528                         namelen += 2;
529                         break;
530                 case 'L':
531                         namelen++;
532                         while (utf_nextu2(&utf_ptr) != ';')
533                                 namelen++;
534                         namelen += 2;
535                         break;
536                 case '(':
537                         break;
538                 default:
539                         assert(0);
540                 }
541         }
542
543
544         /* reallocate memory */
545
546         i = strlen(name);
547
548         newname = DMNEW(char, namelen);
549         MCOPY(newname, name, char, i);
550
551         utf_ptr = desc->text;
552
553         newname[i++] = '_';
554         newname[i++] = '_';
555
556         while ((c = utf_nextu2(&utf_ptr)) != ')') {
557                 switch (c) {
558                 case 'Z':
559                 case 'B':
560                 case 'C':
561                 case 'S':
562                 case 'J':
563                 case 'I':
564                 case 'F':
565                 case 'D':
566                         newname[i++] = c;
567                         break;
568                 case '[':
569                         newname[i++] = '_';
570                         newname[i++] = '3';
571                         break;
572                 case 'L':
573                         newname[i++] = 'L';
574                         while ((c = utf_nextu2(&utf_ptr)) != ';')
575                                 if (((c >= 'a') && (c <= 'z')) ||
576                                         ((c >= 'A') && (c <= 'Z')) ||
577                                         ((c >= '0') && (c <= '9')))
578                                         newname[i++] = c;
579                                 else
580                                         newname[i++] = '_';
581                         newname[i++] = '_';
582                         newname[i++] = '2';
583                         break;
584                 case '(':
585                         break;
586                 default:
587                         assert(0);
588                 }
589         }
590
591         /* close string */
592
593         newname[i] = '\0';
594
595         return newname;
596 }
597
598
599 /* native_resolve_function *****************************************************
600
601    Resolves a native function, maybe from a dynamic library.
602
603 *******************************************************************************/
604
605 functionptr native_resolve_function(methodinfo *m)
606 {
607         lt_ptr                     sym;
608         char                      *name;
609         char                      *newname;
610         s4                         namelen;
611         char                      *utf_ptr;
612         char                      *utf_endptr;
613         s4                         dumpsize;
614         hashtable_library_loader_entry *le;
615         hashtable_library_name_entry   *ne;
616         u4                         key;     /* hashkey                            */
617         u4                         slot;    /* slot in hashtable                  */
618         u4                         i;
619
620
621         /* verbose output */
622
623         if (opt_verbosejni) {
624                 printf("[Dynamic-linking native method ");
625                 utf_display_classname(m->class->name);
626                 printf(".");
627                 utf_display(m->name);
628                 printf(" ... ");
629         }
630                 
631         /* calculate length of native function name */
632
633         namelen = strlen("Java_") + utf_strlen(m->class->name) + strlen("_") +
634                 utf_strlen(m->name) + strlen("0");
635
636         /* check for underscores in class name */
637
638         utf_ptr = m->class->name->text;
639         utf_endptr = UTF_END(m->class->name);
640
641         while (utf_ptr < utf_endptr)
642                 if (utf_nextu2(&utf_ptr) == '_')
643                         namelen++;
644
645         /* check for underscores in method name */
646
647         utf_ptr = m->name->text;
648         utf_endptr = UTF_END(m->name);
649
650         while (utf_ptr < utf_endptr)
651                 if (utf_nextu2(&utf_ptr) == '_')
652                         namelen++;
653
654         /* allocate memory */
655
656         dumpsize = dump_size();
657
658         name = DMNEW(char, namelen);
659
660
661         /* generate name of native functions */
662
663         strcpy(name, "Java_");
664         i = strlen("Java_");
665
666         utf_ptr = m->class->name->text;
667         utf_endptr = UTF_END(m->class->name);
668
669         for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
670                 name[i] = *utf_ptr;
671
672                 /* escape sequence for '_' is '_1' */
673
674                 if (name[i] == '_')
675                         name[++i] = '1';
676
677                 /* replace '/' with '_' */
678
679                 if (name[i] == '/')
680                         name[i] = '_';
681         }
682
683         /* seperator between class and method */
684
685         name[i++] = '_';
686
687         utf_ptr = m->name->text;
688         utf_endptr = UTF_END(m->name);
689
690         for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
691                 name[i] = *utf_ptr;
692
693                 /* escape sequence for '_' is '_1' */
694
695                 if (name[i] == '_')
696                         name[++i] = '1';
697         }
698
699         /* close string */
700
701         name[i] = '\0';
702
703
704         /* generate overloaded function (having the types in it's name)           */
705
706         newname = native_make_overloaded_function(name, m->descriptor);
707
708         /* check the library hash entries of the classloader of the methods's     */
709         /* class                                                                  */
710
711         sym = NULL;
712
713         /* normally addresses are aligned to 4, 8 or 16 bytes */
714
715         key  = ((u4) (ptrint) m->class->classloader) >> 4;    /* align to 16-byte */
716         slot = key & (hashtable_library.size - 1);
717         le   = hashtable_library.ptr[slot];
718
719         /* iterate through loaders in this hash slot */
720
721         while (le && !sym) {
722                 /* iterate through names in this loader */
723
724                 ne = le->namelink;
725                         
726                 while (ne && !sym) {
727                         sym = lt_dlsym(ne->handle, name);
728
729                         if (!sym)
730                                 sym = lt_dlsym(ne->handle, newname);
731
732                         ne = ne->hashlink;
733                 }
734
735                 le = le->hashlink;
736         }
737
738         if (sym)
739                 if (opt_verbosejni)
740                         printf("JNI ]\n");
741
742
743         /* if not found, try to find the native function symbol in the main       */
744         /* program                                                                */
745
746         if (!sym) {
747                 sym = lt_dlsym(mainhandle, name);
748
749                 if (!sym)
750                         sym = lt_dlsym(mainhandle, newname);
751
752                 if (sym)
753                         if (opt_verbosejni)
754                                 printf("internal ]\n");
755         }
756
757
758         /* no symbol found? throw exception */
759
760         if (!sym)
761                 *exceptionptr =
762                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
763                                                                          m->name);
764
765         /* release memory */
766
767         dump_release(dumpsize);
768
769         return (functionptr) (ptrint) sym;
770 }
771 #endif /* !defined(ENABLE_STATICVM) */
772
773
774 /* native_new_and_init *********************************************************
775
776    Creates a new object on the heap and calls the initializer.
777    Returns the object pointer or NULL if memory is exhausted.
778                         
779 *******************************************************************************/
780
781 java_objectheader *native_new_and_init(classinfo *c)
782 {
783         methodinfo *m;
784         java_objectheader *o;
785
786         if (!c)
787                 return *exceptionptr;
788
789         /* create object */
790
791         o = builtin_new(c);
792         
793         if (!o)
794                 return NULL;
795
796         /* find initializer */
797
798         m = class_findmethod(c, utf_init, utf_void__void);
799                                                       
800         /* initializer not found */
801
802         if (!m)
803                 return o;
804
805         /* call initializer */
806
807         asm_calljavafunction(m, o, NULL, NULL, NULL);
808
809         return o;
810 }
811
812
813 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
814 {
815         methodinfo *m;
816         java_objectheader *o;
817
818         if (!c)
819                 return *exceptionptr;
820
821         /* create object */
822
823         o = builtin_new(c);
824
825         if (!o)
826                 return NULL;
827
828         /* find initializer */
829
830         m = class_resolveclassmethod(c,
831                                                                  utf_init,
832                                                                  utf_java_lang_String__void,
833                                                                  NULL,
834                                                                  true);
835
836         /* initializer not found */
837
838         if (!m)
839                 return NULL;
840
841         /* call initializer */
842
843         asm_calljavafunction(m, o, s, NULL, NULL);
844
845         return o;
846 }
847
848
849 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
850 {
851         methodinfo *m;
852         java_objectheader *o;
853
854         if (!c)
855                 return *exceptionptr;
856
857         /* create object */
858
859         o = builtin_new(c);
860         
861         if (!o)
862                 return NULL;
863
864         /* find initializer */
865
866         m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
867
868         /* initializer not found  */
869
870         if (!m)
871                 return NULL;
872
873         /* call initializer */
874
875         asm_calljavafunction(m, o, (void *) (ptrint) i, NULL, NULL);
876
877         return o;
878 }
879
880
881 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
882 {
883         methodinfo *m;
884         java_objectheader *o;
885
886         if (!c)
887                 return *exceptionptr;
888
889         /* create object */
890
891         o = builtin_new(c);
892         
893         if (!o)
894                 return NULL;
895
896         /* find initializer */
897
898         m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
899                                                       
900         /* initializer not found */
901
902         if (!m)
903                 return NULL;
904
905         /* call initializer */
906
907         asm_calljavafunction(m, o, t, NULL, NULL);
908
909         return o;
910 }
911
912
913 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
914 {
915     *dest = src;
916 #if 0
917     /* XXX this kind of copying does not work (in the general
918      * case). The interface tables would have to be copied, too. I
919      * don't see why we should make a copy anyway. -Edwin
920      */
921         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
922         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
923         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
924 #endif
925 }
926
927
928 /******************************************************************************************                                                                                                             
929
930         creates method signature (excluding return type) from array of 
931         class-objects representing the parameters of the method 
932
933 *******************************************************************************************/
934
935
936 utf *create_methodsig(java_objectarray* types, char *retType)
937 {
938     char *buffer;       /* buffer for building the desciptor */
939     char *pos;          /* current position in buffer */
940     utf *result;        /* the method signature */
941     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
942     u4 i, j;
943  
944     if (!types) return NULL;
945
946     /* determine required buffer-size */    
947     for (i = 0; i < types->header.size; i++) {
948                 classinfo *c = (classinfo *) types->data[i];
949                 buffer_size  = buffer_size + c->name->blength + 2;
950     }
951
952     if (retType) buffer_size += strlen(retType);
953
954     /* allocate buffer */
955     buffer = MNEW(char, buffer_size);
956     pos    = buffer;
957     
958     /* method-desciptor starts with parenthesis */
959     *pos++ = '(';
960
961     for (i = 0; i < types->header.size; i++) {
962                 char ch;           
963
964                 /* current argument */
965             classinfo *c = (classinfo *) types->data[i];
966
967             /* current position in utf-text */
968             char *utf_ptr = c->name->text; 
969             
970             /* determine type of argument */
971             if ((ch = utf_nextu2(&utf_ptr)) == '[') {
972                 /* arrayclass */
973                 for (utf_ptr--; utf_ptr < UTF_END(c->name); utf_ptr++) {
974                                 *pos++ = *utf_ptr; /* copy text */
975                         }
976
977             } else {            
978                         /* check for primitive types */
979                         for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
980                                 char *utf_pos   = utf_ptr - 1;
981                                 char *primitive = primitivetype_table[j].wrapname;
982
983                                 /* compare text */
984                                 while (utf_pos < UTF_END(c->name)) {
985                                         if (*utf_pos++ != *primitive++) goto nomatch;
986                                 }
987
988                                 /* primitive type found */
989                                 *pos++ = primitivetype_table[j].typesig;
990                                 goto next_type;
991
992                         nomatch:
993                                 ;
994                         }
995
996                         /* no primitive type and no arrayclass, so must be object */
997                         *pos++ = 'L';
998
999                         /* copy text */
1000                         for (utf_ptr--; utf_ptr < UTF_END(c->name); utf_ptr++) {
1001                                 *pos++ = *utf_ptr;
1002                         }
1003
1004                         *pos++ = ';';
1005
1006                 next_type:
1007                         ;
1008                 }  
1009     }       
1010
1011     *pos++ = ')';
1012
1013     if (retType) {
1014                 for (i = 0; i < strlen(retType); i++) {
1015                         *pos++ = retType[i];
1016                 }
1017     }
1018
1019     /* create utf-string */
1020     result = utf_new(buffer, (pos - buffer));
1021     MFREE(buffer, char, buffer_size);
1022
1023     return result;
1024 }
1025
1026
1027 /* native_get_parametertypes ***************************************************
1028
1029    Use the descriptor of a method to generate a java/lang/Class array
1030    which contains the classes of the parametertypes of the method.
1031
1032 *******************************************************************************/
1033
1034 java_objectarray *native_get_parametertypes(methodinfo *m)
1035 {
1036         methoddesc       *md;
1037         typedesc         *paramtypes;
1038         s4                paramcount;
1039     java_objectarray *oa;
1040         s4                i;
1041
1042         md = m->parseddesc;
1043
1044         /* is the descriptor fully parsed? */
1045
1046         if (!m->parseddesc->params)
1047                 if (!descriptor_params_from_paramtypes(md, m->flags))
1048                         return NULL;
1049
1050         paramtypes = md->paramtypes;
1051         paramcount = md->paramcount;
1052
1053         /* skip `this' pointer */
1054
1055         if (!(m->flags & ACC_STATIC)) {
1056                 paramtypes++;
1057                 paramcount--;
1058         }
1059
1060         /* create class-array */
1061
1062         oa = builtin_anewarray(paramcount, class_java_lang_Class);
1063
1064         if (!oa)
1065                 return NULL;
1066
1067     /* get classes */
1068
1069         for (i = 0; i < paramcount; i++)
1070                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false,
1071                                                                                  (classinfo **) &oa->data[i]))
1072                         return NULL;
1073
1074         return oa;
1075 }
1076
1077
1078 /* native_get_exceptiontypes ***************************************************
1079
1080    Get the exceptions which can be thrown by a method.
1081
1082 *******************************************************************************/
1083
1084 java_objectarray *native_get_exceptiontypes(methodinfo *m)
1085 {
1086         java_objectarray *oa;
1087         classinfo        *c;
1088         u2                i;
1089
1090         /* create class-array */
1091
1092         oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
1093
1094         if (!oa)
1095                 return NULL;
1096
1097         for (i = 0; i < m->thrownexceptionscount; i++) {
1098                 if (!resolve_classref_or_classinfo(NULL, m->thrownexceptions[i],
1099                                                                                    resolveEager, true, false, &c))
1100                         return NULL;
1101
1102                 oa->data[i] = (java_objectheader *) c;
1103         }
1104
1105         return oa;
1106 }
1107
1108
1109 /* native_get_returntype *******************************************************
1110
1111    Get the returntype class of a method.
1112
1113 *******************************************************************************/
1114
1115 classinfo *native_get_returntype(methodinfo *m)
1116 {
1117         classinfo *c;
1118
1119         if (!resolve_class_from_typedesc(&(m->parseddesc->returntype), true, false,
1120                                                                          &c))
1121                 return NULL;
1122
1123         return c;
1124 }
1125
1126
1127 /*****************************************************************************/
1128 /*****************************************************************************/
1129
1130
1131 /*--------------------------------------------------------*/
1132 void printNativeCall(nativeCall nc) {
1133   int i,j;
1134
1135   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1136   for (i=0; i<nc.methCnt; i++) {  
1137       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1138
1139     for (j=0; j<nc.callCnt[i]; j++) {  
1140         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1141         nc.methods[i].methodCalls[j].classname, 
1142         nc.methods[i].methodCalls[j].methodname, 
1143         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1144       }
1145     }
1146   printf("-+++++--------------------\n");fflush(stdout);
1147 }
1148
1149 /*--------------------------------------------------------*/
1150 void printCompNativeCall(nativeCompCall nc) {
1151   int i,j;
1152   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
1153   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1154   utf_display(nc.classname); fflush(stdout);
1155   
1156   for (i=0; i<nc.methCnt; i++) {  
1157     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1158     utf_display(nc.methods[i].methodname); fflush(stdout);
1159     utf_display(nc.methods[i].descriptor);fflush(stdout);
1160     printf("\n");fflush(stdout);
1161
1162     for (j=0; j<nc.callCnt[i]; j++) {  
1163       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1164         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1165         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1166         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1167         printf("\n");fflush(stdout);
1168       }
1169     }
1170 printf("---------------------\n");fflush(stdout);
1171 }
1172
1173
1174 /*--------------------------------------------------------*/
1175 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1176 {
1177     int i = 0;
1178     int j = 0;
1179     int cnt = 0;
1180     classMeth mc;
1181     mc.i_class = i;
1182     mc.j_method = j;
1183     mc.methCnt = cnt;
1184
1185     return mc;
1186 }
1187
1188 /*--------------------------------------------------------*/
1189 nativeCall* findNativeClassCalls(char *aclassname ) {
1190 int i;
1191
1192 for (i=0;i<NATIVECALLSSIZE; i++) {
1193    /* convert table to utf later to speed up search */ 
1194    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1195         return &nativeCalls[i];
1196    }
1197
1198 return NULL;
1199 }
1200 /*--------------------------------------------------------*/
1201 /*--------------------------------------------------------*/
1202 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1203   int i,j;
1204
1205
1206   ncc->classname = utf_new_char(nc.classname); 
1207   ncc->methCnt = nc.methCnt;
1208   
1209   for (i=0; i<nc.methCnt; i++) {  
1210     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1211     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1212     ncc->callCnt[i] = nc.callCnt[i];
1213
1214     for (j=0; j<nc.callCnt[i]; j++) {  
1215
1216         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1217
1218         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1219           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1220           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1221           }
1222         else {
1223           ncc->methods[i].methodCalls[j].methodname = NULL;
1224           ncc->methods[i].methodCalls[j].descriptor = NULL;
1225           }
1226       }
1227     }
1228 }
1229
1230
1231
1232 /*--------------------------------------------------------*/
1233
1234 bool natcall2utf(bool natcallcompdone) {
1235 int i;
1236
1237 if (natcallcompdone) 
1238         return true;
1239
1240 for (i=0;i<NATIVECALLSSIZE; i++) {
1241    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1242    }
1243
1244 return true;
1245 }
1246
1247 /*
1248  * These are local overrides for various environment variables in Emacs.
1249  * Please do not remove this and leave it at the end of the file, where
1250  * Emacs will automagically detect them.
1251  * ---------------------------------------------------------------------
1252  * Local variables:
1253  * mode: c
1254  * indent-tabs-mode: t
1255  * c-basic-offset: 4
1256  * tab-width: 4
1257  * End:
1258  */