* Removed all Id tags.
[cacao.git] / src / native / native.c
1 /* src/native/native.c - table of native functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <ctype.h>
32
33 #if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H)
34 # include <ltdl.h>
35 #endif
36
37 #include <stdint.h>
38
39 #include "vm/types.h"
40
41 #include "mm/memory.h"
42
43 #include "native/jni.h"
44 #include "native/native.h"
45
46 #include "native/vm/nativevm.h"
47
48 #include "threads/lock-common.h"
49
50 #include "toolbox/avl.h"
51 #include "toolbox/hashtable.h"
52 #include "toolbox/logging.h"
53
54 #include "vm/builtin.h"
55 #include "vm/exceptions.h"
56 #include "vm/global.h"
57 #include "vm/stringlocal.h"
58 #include "vm/vm.h"
59
60 #include "vm/jit/asmpart.h"
61 #include "vm/jit/jit.h"
62
63 #include "vmcore/loader.h"
64 #include "vmcore/options.h"
65 #include "vm/resolve.h"
66
67 #if defined(ENABLE_JVMTI)
68 #include "native/jvmti/cacaodbg.h"
69 #endif
70
71
72 /* include table of native functions ******************************************/
73
74 #if defined(WITH_STATIC_CLASSPATH)
75 # include "native/nativetable.inc"
76 #endif
77
78
79 /* tables for methods *********************************************************/
80
81 #if defined(WITH_STATIC_CLASSPATH)
82 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
83
84 /* table for fast string comparison */
85 static nativecompref nativecomptable[NATIVETABLESIZE];
86
87 /* string comparsion table initialized */
88 static bool nativecompdone = false;
89 #endif
90
91
92 /* global variables ***********************************************************/
93
94 static avl_tree_t *tree_native_methods;
95
96 #if defined(ENABLE_LTDL)
97 static hashtable *hashtable_library;
98 #endif
99
100
101 /* prototypes *****************************************************************/
102
103 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
104
105
106 /* native_init *****************************************************************
107
108    Initializes the native subsystem.
109
110 *******************************************************************************/
111
112 bool native_init(void)
113 {
114 #if defined(ENABLE_LTDL)
115         /* initialize libltdl */
116
117         if (lt_dlinit())
118                 vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror());
119
120         /* initialize library hashtable, 10 entries should be enough */
121
122         hashtable_library = NEW(hashtable);
123
124         hashtable_create(hashtable_library, 10);
125 #endif
126
127         /* initialize the native methods table */
128
129         tree_native_methods = avl_create(&native_tree_native_methods_comparator);
130
131         /* everything's ok */
132
133         return true;
134 }
135
136
137 /* native_tree_native_methods_comparator ***************************************
138
139    Comparison function for AVL tree of native methods.
140
141    IN:
142        treenode....node in the tree
143            node........node to compare with tree-node
144
145    RETURN VALUE:
146        -1, 0, +1
147
148 *******************************************************************************/
149
150 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
151 {
152         const native_methods_node_t *treenmn;
153         const native_methods_node_t *nmn;
154
155         treenmn = treenode;
156         nmn     = node;
157
158         /* these are for walking the tree */
159
160         if (treenmn->classname < nmn->classname)
161                 return -1;
162         else if (treenmn->classname > nmn->classname)
163                 return 1;
164
165         if (treenmn->name < nmn->name)
166                 return -1;
167         else if (treenmn->name > nmn->name)
168                 return 1;
169
170         if (treenmn->descriptor < nmn->descriptor)
171                 return -1;
172         else if (treenmn->descriptor > nmn->descriptor)
173                 return 1;
174
175         /* all pointers are equal, we have found the entry */
176
177         return 0;
178 }
179
180
181 /* native_make_overloaded_function *********************************************
182
183    XXX
184
185 *******************************************************************************/
186
187 #if !defined(WITH_STATIC_CLASSPATH)
188 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
189 {
190         char *newname;
191         s4    namelen;
192         char *utf_ptr;
193         u2    c;
194         s4    i;
195         s4    dumpsize;
196         utf  *u;
197
198         /* mark memory */
199
200         dumpsize = dump_size();
201
202         utf_ptr = descriptor->text;
203         namelen = strlen(name->text) + strlen("__") + strlen("0");
204
205         /* calculate additional length */
206
207         while ((c = utf_nextu2(&utf_ptr)) != ')') {
208                 switch (c) {
209                 case 'Z':
210                 case 'B':
211                 case 'C':
212                 case 'S':
213                 case 'I':
214                 case 'J':
215                 case 'F':
216                 case 'D':
217                         namelen++;
218                         break;
219                 case '[':
220                         namelen += 2;
221                         break;
222                 case 'L':
223                         namelen++;
224                         while (utf_nextu2(&utf_ptr) != ';')
225                                 namelen++;
226                         namelen += 2;
227                         break;
228                 case '(':
229                         break;
230                 default:
231                         assert(0);
232                 }
233         }
234
235         /* reallocate memory */
236
237         i = strlen(name->text);
238
239         newname = DMNEW(char, namelen);
240         MCOPY(newname, name->text, char, i);
241
242         utf_ptr = descriptor->text;
243
244         newname[i++] = '_';
245         newname[i++] = '_';
246
247         while ((c = utf_nextu2(&utf_ptr)) != ')') {
248                 switch (c) {
249                 case 'Z':
250                 case 'B':
251                 case 'C':
252                 case 'S':
253                 case 'J':
254                 case 'I':
255                 case 'F':
256                 case 'D':
257                         newname[i++] = c;
258                         break;
259                 case '[':
260                         newname[i++] = '_';
261                         newname[i++] = '3';
262                         break;
263                 case 'L':
264                         newname[i++] = 'L';
265                         while ((c = utf_nextu2(&utf_ptr)) != ';')
266                                 if (((c >= 'a') && (c <= 'z')) ||
267                                         ((c >= 'A') && (c <= 'Z')) ||
268                                         ((c >= '0') && (c <= '9')))
269                                         newname[i++] = c;
270                                 else
271                                         newname[i++] = '_';
272                         newname[i++] = '_';
273                         newname[i++] = '2';
274                         break;
275                 case '(':
276                         break;
277                 default:
278                         assert(0);
279                 }
280         }
281
282         /* close string */
283
284         newname[i] = '\0';
285
286         /* make a utf-string */
287
288         u = utf_new_char(newname);
289
290         /* release memory */
291
292         dump_release(dumpsize);
293
294         return u;
295 }
296
297
298 /* native_insert_char **********************************************************
299
300    Inserts the passed UTF character into the native method name.  If
301    necessary it is escaped properly.
302
303 *******************************************************************************/
304
305 static s4 native_insert_char(char *name, u4 pos, u2 c)
306 {
307         s4 val;
308         s4 i;
309
310         switch (c) {
311         case '/':
312         case '.':
313                 /* replace '/' or '.' with '_' */
314                 name[pos] = '_';
315                 break;
316
317         case '_':
318                 /* escape sequence for '_' is '_1' */
319                 name[pos]   = '_';
320                 name[++pos] = '1';
321                 break;
322
323         case ';':
324                 /* escape sequence for ';' is '_2' */
325                 name[pos]   = '_';
326                 name[++pos] = '2';
327                 break;
328
329         case '[':
330                 /* escape sequence for '[' is '_1' */
331                 name[pos]   = '_';
332                 name[++pos] = '3';
333                 break;
334
335         default:
336                 if (isalnum(c))
337                         name[pos] = c;
338                 else {
339                         /* unicode character */
340                         name[pos]   = '_';
341                         name[++pos] = '0';
342
343                         for (i = 0; i < 4; ++i) {
344                                 val = c & 0x0f;
345                                 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
346                                 c >>= 4;
347                         }
348
349                         pos += 4;
350                 }
351                 break;
352         }
353
354         /* return the new buffer index */
355
356         return pos;
357 }
358
359
360 /* native_method_symbol ********************************************************
361
362    Generate a method-symbol string out of the class name and the
363    method name.
364
365 *******************************************************************************/
366
367 static utf *native_method_symbol(utf *classname, utf *methodname)
368 {
369         char *name;
370         s4    namelen;
371         char *utf_ptr;
372         char *utf_endptr;
373         u2    c;
374         u4    pos;
375         s4    dumpsize;
376         utf  *u;
377
378         /* mark memory */
379
380         dumpsize = dump_size();
381
382         /* Calculate length of native function name.  We multiply the
383            class and method name length by 6 as this is the maxium
384            escape-sequence that can be generated (unicode). */
385
386         namelen =
387                 strlen("Java_") +
388                 utf_get_number_of_u2s(classname) * 6 +
389                 strlen("_") +
390                 utf_get_number_of_u2s(methodname) * 6 +
391                 strlen("0");
392
393         /* allocate memory */
394
395         name = DMNEW(char, namelen);
396
397         /* generate name of native functions */
398
399         strcpy(name, "Java_");
400         pos = strlen("Java_");
401
402         utf_ptr    = classname->text;
403         utf_endptr = UTF_END(classname);
404
405         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
406                 c   = *utf_ptr;
407                 pos = native_insert_char(name, pos, c);
408         }
409
410         /* seperator between class and method */
411
412         name[pos++] = '_';
413
414         utf_ptr    = methodname->text;
415         utf_endptr = UTF_END(methodname);
416
417         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
418                 c   = *utf_ptr;
419                 pos = native_insert_char(name, pos, c);
420         }
421
422         /* close string */
423
424         name[pos] = '\0';
425
426         /* check for an buffer overflow */
427
428         assert(pos <= namelen);
429
430         /* make a utf-string */
431
432         u = utf_new_char(name);
433
434         /* release memory */
435
436         dump_release(dumpsize);
437
438         return u;
439 }
440
441
442 /* native_method_register ******************************************************
443
444    Register a native method in the native method table.
445
446 *******************************************************************************/
447
448 void native_method_register(utf *classname, const JNINativeMethod *methods,
449                                                         int32_t count)
450 {
451         native_methods_node_t *nmn;
452         utf                   *name;
453         utf                   *descriptor;
454         int32_t                i;
455
456         /* insert all methods passed */
457
458         for (i = 0; i < count; i++) {
459                 if (opt_verbosejni) {
460                         printf("[Registering JNI native method ");
461                         utf_display_printable_ascii_classname(classname);
462                         printf(".%s]\n", methods[i].name);
463                 }
464
465                 /* generate the utf8 names */
466
467                 name       = utf_new_char(methods[i].name);
468                 descriptor = utf_new_char(methods[i].signature);
469
470                 /* allocate a new tree node */
471
472                 nmn = NEW(native_methods_node_t);
473
474                 nmn->classname  = classname;
475                 nmn->name       = name;
476                 nmn->descriptor = descriptor;
477                 nmn->function   = (functionptr) (ptrint) methods[i].fnPtr;
478
479                 /* insert the method into the tree */
480
481                 avl_insert(tree_native_methods, nmn);
482         }
483 }
484
485
486 /* native_method_find **********************************************************
487
488    Find a native method in the native method table.
489
490 *******************************************************************************/
491
492 static functionptr native_method_find(methodinfo *m)
493 {
494         native_methods_node_t  tmpnmn;
495         native_methods_node_t *nmn;
496
497         /* fill the temporary structure used for searching the tree */
498
499         tmpnmn.classname  = m->class->name;
500         tmpnmn.name       = m->name;
501         tmpnmn.descriptor = m->descriptor;
502
503         /* find the entry in the AVL-tree */
504
505         nmn = avl_find(tree_native_methods, &tmpnmn);
506
507         if (nmn == NULL)
508                 return NULL;
509
510         return nmn->function;
511 }
512
513
514 /* native_library_open *********************************************************
515
516    Open a native library with the given utf8 name.
517
518 *******************************************************************************/
519
520 #if defined(ENABLE_LTDL)
521 lt_dlhandle native_library_open(utf *filename)
522 {
523         lt_dlhandle handle;
524
525         if (opt_verbosejni) {
526                 printf("[Loading native library ");
527                 utf_display_printable_ascii(filename);
528                 printf(" ... ");
529         }
530
531         /* try to open the library */
532
533         handle = lt_dlopen(filename->text);
534
535         if (handle == NULL) {
536                 if (opt_verbose) {
537                         log_start();
538                         log_print("native_library_load: lt_dlopen failed: ");
539                         log_print(lt_dlerror());
540                         log_finish();
541                 }
542
543                 return NULL;
544         }
545
546         return handle;
547 }
548 #endif
549
550
551 /* native_library_add **********************************************************
552
553    Adds an entry to the native library hashtable.
554
555 *******************************************************************************/
556
557 #if defined(ENABLE_LTDL)
558 void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
559 {
560         hashtable_library_loader_entry *le;
561         hashtable_library_name_entry   *ne; /* library name                       */
562         u4   key;                           /* hashkey                            */
563         u4   slot;                          /* slot in hashtable                  */
564
565         LOCK_MONITOR_ENTER(hashtable_library->header);
566
567         /* normally addresses are aligned to 4, 8 or 16 bytes */
568
569         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
570         slot = key & (hashtable_library->size - 1);
571         le   = hashtable_library->ptr[slot];
572
573         /* search external hash chain for the entry */
574
575         while (le) {
576                 if (le->loader == loader)
577                         break;
578
579                 le = le->hashlink;                  /* next element in external chain */
580         }
581
582         /* no loader found? create a new entry */
583
584         if (le == NULL) {
585                 le = NEW(hashtable_library_loader_entry);
586
587                 le->loader   = loader;
588                 le->namelink = NULL;
589
590                 /* insert entry into hashtable */
591
592                 le->hashlink =
593                         (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
594                 hashtable_library->ptr[slot] = le;
595
596                 /* update number of hashtable-entries */
597
598                 hashtable_library->entries++;
599         }
600
601
602         /* search for library name */
603
604         ne = le->namelink;
605
606         while (ne) {
607                 if (ne->name == filename) {
608                         LOCK_MONITOR_EXIT(hashtable_library->header);
609
610                         return;
611                 }
612
613                 ne = ne->hashlink;                  /* next element in external chain */
614         }
615
616         /* not found? add the library name to the classloader */
617
618         ne = NEW(hashtable_library_name_entry);
619
620         ne->name   = filename;
621         ne->handle = handle;
622
623         /* insert entry into external chain */
624
625         ne->hashlink = le->namelink;
626         le->namelink = ne;
627
628         LOCK_MONITOR_EXIT(hashtable_library->header);
629 }
630 #endif
631
632
633 /* native_library_find *********************************************************
634
635    Find an entry in the native library hashtable.
636
637 *******************************************************************************/
638
639 #if defined(ENABLE_LTDL)
640 hashtable_library_name_entry *native_library_find(utf *filename,
641                                                                                                   classloader *loader)
642 {
643         hashtable_library_loader_entry *le;
644         hashtable_library_name_entry   *ne; /* library name                       */
645         u4   key;                           /* hashkey                            */
646         u4   slot;                          /* slot in hashtable                  */
647
648         /* normally addresses are aligned to 4, 8 or 16 bytes */
649
650         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
651         slot = key & (hashtable_library->size - 1);
652         le   = hashtable_library->ptr[slot];
653
654         /* search external hash chain for the entry */
655
656         while (le) {
657                 if (le->loader == loader)
658                         break;
659
660                 le = le->hashlink;                  /* next element in external chain */
661         }
662
663         /* no loader found? return NULL */
664
665         if (le == NULL)
666                 return NULL;
667
668         /* search for library name */
669
670         ne = le->namelink;
671
672         while (ne) {
673                 if (ne->name == filename)
674                         return ne;
675
676                 ne = ne->hashlink;                  /* next element in external chain */
677         }
678
679         /* return entry, if no entry was found, ne is NULL */
680
681         return ne;
682 }
683 #endif /* !defined(WITH_STATIC_CLASSPATH) */
684
685
686 /* native_findfunction *********************************************************
687
688    Looks up a method (must have the same class name, method name,
689    descriptor and 'static'ness) and returns a function pointer to it.
690    Returns: function pointer or NULL (if there is no such method)
691
692    Remark: For faster operation, the names/descriptors are converted
693    from C strings to Unicode the first time this function is called.
694
695 *******************************************************************************/
696
697 #if defined(WITH_STATIC_CLASSPATH)
698 functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
699                                                                 bool isstatic)
700 {
701         /* entry of table for fast string comparison */
702         struct nativecompref *n;
703         s4 i;
704
705         isstatic = isstatic ? true : false;
706         
707         if (!nativecompdone) {
708                 for (i = 0; i < NATIVETABLESIZE; i++) {
709                         nativecomptable[i].classname  = 
710                                 utf_new_char(nativetable[i].classname);
711
712                         nativecomptable[i].methodname = 
713                                 utf_new_char(nativetable[i].methodname);
714
715                         nativecomptable[i].descriptor =
716                                 utf_new_char(nativetable[i].descriptor);
717
718                         nativecomptable[i].isstatic   = nativetable[i].isstatic;
719                         nativecomptable[i].func       = nativetable[i].func;
720                 }
721
722                 nativecompdone = true;
723         }
724
725         for (i = 0; i < NATIVETABLESIZE; i++) {
726                 n = &(nativecomptable[i]);
727
728                 if (cname == n->classname && mname == n->methodname &&
729                     desc == n->descriptor && isstatic == n->isstatic)
730                         return n->func;
731         }
732
733         /* no function was found, throw exception */
734
735         exceptions_throw_unsatisfiedlinkerror(mname);
736
737         return NULL;
738 }
739 #endif /* defined(WITH_STATIC_CLASSPATH) */
740
741
742 /* native_resolve_function *****************************************************
743
744    Resolves a native function, maybe from a dynamic library.
745
746 *******************************************************************************/
747
748 functionptr native_resolve_function(methodinfo *m)
749 {
750         classloader                    *cl;
751         utf                            *name;
752         utf                            *newname;
753         functionptr                     f;
754 #if defined(ENABLE_LTDL)
755         hashtable_library_loader_entry *le;
756         hashtable_library_name_entry   *ne;
757         u4                              key;    /* hashkey                        */
758         u4                              slot;   /* slot in hashtable              */
759 #endif
760 #if defined(WITH_CLASSPATH_SUN)
761         methodinfo                     *method_findNative;
762         java_handle_t                  *s;
763 #endif
764
765         cl = m->class->classloader;
766
767         /* verbose output */
768
769         if (opt_verbosejni) {
770                 printf("[Dynamic-linking native method ");
771                 utf_display_printable_ascii_classname(m->class->name);
772                 printf(".");
773                 utf_display_printable_ascii(m->name);
774                 printf(" ... ");
775         }
776
777         /* generate method symbol string */
778
779         name = native_method_symbol(m->class->name, m->name);
780
781         /* generate overloaded function (having the types in it's name)           */
782
783         newname = native_make_overloaded_function(name, m->descriptor);
784
785         /* check the library hash entries of the classloader of the
786            methods's class  */
787
788         f = NULL;
789
790 #if defined(ENABLE_LTDL)
791         /* normally addresses are aligned to 4, 8 or 16 bytes */
792
793         key  = ((u4) (ptrint) cl) >> 4;                       /* align to 16-byte */
794         slot = key & (hashtable_library->size - 1);
795         le   = hashtable_library->ptr[slot];
796
797         /* iterate through loaders in this hash slot */
798
799         while ((le != NULL) && (f == NULL)) {
800                 /* iterate through names in this loader */
801
802                 ne = le->namelink;
803                         
804                 while ((ne != NULL) && (f == NULL)) {
805                         f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text);
806
807                         if (f == NULL)
808                                 f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
809
810                         ne = ne->hashlink;
811                 }
812
813                 le = le->hashlink;
814         }
815
816 # if defined(WITH_CLASSPATH_SUN)
817         if (f == NULL) {
818                 /* We can resolve the function directly from
819                    java.lang.ClassLoader as it's a static function. */
820                 /* XXX should be done in native_init */
821
822                 method_findNative =
823                         class_resolveclassmethod(class_java_lang_ClassLoader,
824                                                                          utf_findNative,
825                                                                          utf_java_lang_ClassLoader_java_lang_String__J,
826                                                                          class_java_lang_ClassLoader,
827                                                                          true);
828
829                 if (method_findNative == NULL)
830                         return NULL;
831
832                 /* try the normal name */
833
834                 s = javastring_new(name);
835
836                 f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
837                                                                                                                  NULL, cl, s);
838
839                 /* if not found, try the mangled name */
840
841                 if (f == NULL) {
842                         s = javastring_new(newname);
843
844                         f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
845                                                                                                                          NULL, cl, s);
846                 }
847         }
848 # endif
849
850         if (f != NULL)
851                 if (opt_verbosejni)
852                         printf("JNI ]\n");
853 #endif
854
855         /* If not found, try to find the native function symbol in the
856            main program. */
857
858         if (f == NULL) {
859                 f = native_method_find(m);
860
861                 if (f != NULL)
862                         if (opt_verbosejni)
863                                 printf("internal ]\n");
864         }
865
866 #if defined(ENABLE_JVMTI)
867         /* fire Native Method Bind event */
868         if (jvmti) jvmti_NativeMethodBind(m, f, &f);
869 #endif
870
871         /* no symbol found? throw exception */
872
873         if (f == NULL) {
874                 if (opt_verbosejni)
875                         printf("failed ]\n");
876
877                 exceptions_throw_unsatisfiedlinkerror(m->name);
878         }
879
880         return f;
881 }
882 #endif /* !defined(WITH_STATIC_CLASSPATH) */
883
884
885 /* native_new_and_init *********************************************************
886
887    Creates a new object on the heap and calls the initializer.
888    Returns the object pointer or NULL if memory is exhausted.
889                         
890 *******************************************************************************/
891
892 java_handle_t *native_new_and_init(classinfo *c)
893 {
894         methodinfo    *m;
895         java_handle_t *o;
896
897         if (c == NULL)
898                 vm_abort("native_new_and_init: c == NULL");
899
900         /* create object */
901
902         o = builtin_new(c);
903         
904         if (o == NULL)
905                 return NULL;
906
907         /* try to find the initializer */
908
909         m = class_findmethod(c, utf_init, utf_void__void);
910                                                       
911         /* ATTENTION: returning the object here is ok, since the class may
912        not have an initializer */
913
914         if (m == NULL)
915                 return o;
916
917         /* call initializer */
918
919         (void) vm_call_method(m, o);
920
921         return o;
922 }
923
924
925 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
926 {
927         methodinfo    *m;
928         java_handle_t *o;
929
930         if (c == NULL)
931                 vm_abort("native_new_and_init_string: c == NULL");
932
933         /* create object */
934
935         o = builtin_new(c);
936
937         if (o == NULL)
938                 return NULL;
939
940         /* find initializer */
941
942         m = class_findmethod(c, utf_init, utf_java_lang_String__void);
943
944         /* initializer not found */
945
946         if (m == NULL)
947                 return NULL;
948
949         /* call initializer */
950
951         (void) vm_call_method(m, o, s);
952
953         return o;
954 }
955
956
957 /*
958  * These are local overrides for various environment variables in Emacs.
959  * Please do not remove this and leave it at the end of the file, where
960  * Emacs will automagically detect them.
961  * ---------------------------------------------------------------------
962  * Local variables:
963  * mode: c
964  * indent-tabs-mode: t
965  * c-basic-offset: 4
966  * tab-width: 4
967  * End:
968  */