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