- proper link_class call
[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 2151 2005-03-30 19:27:47Z twisti $
34
35 */
36
37
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <time.h>
41 #include <math.h>
42 #include <string.h>
43 #include <assert.h>
44 #include <sys/time.h>
45 #include <utime.h>
46
47 /* Include files for IO functions */
48
49 #include <fcntl.h>
50 #include <dirent.h>
51 #include <sys/types.h>
52 #ifdef _OSF_SOURCE 
53 #include <sys/mode.h>
54 #endif
55 #include <sys/stat.h>
56
57 #include "config.h"
58 #include "cacao/cacao.h"
59 #include "mm/memory.h"
60 #include "native/jni.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Throwable.h"
63 #include "toolbox/logging.h"
64 #include "vm/builtin.h"
65 #include "vm/exceptions.h"
66 #include "vm/global.h"
67 #include "vm/loader.h"
68 #include "vm/options.h"
69 #include "vm/stringlocal.h"
70 #include "vm/tables.h"
71 #include "vm/jit/asmpart.h"
72 #include "vm/jit/jit.h"
73
74
75 /* include table of native functions ******************************************/
76
77 #include "nativetable.inc"
78
79
80 /************* use classinfo structure as java.lang.Class object **************/
81
82 void use_class_as_object(classinfo *c) 
83 {
84         if (!c->classvftbl) {
85                 /* is the class loaded */
86                 if (!c->loaded)
87 /*                      if (!class_load(c)) */
88 /*                              throw_exception_exit(); */
89                         panic("use_class_as_object: class_load should not happen");
90
91                 /* is the class linked */
92                 if (!c->linked)
93                         if (!link_class(c))
94                                 throw_exception_exit();
95
96                 /*if (class_java_lang_Class ==0) panic("java/lang/Class not loaded in use_class_as_object");
97                 if (class_java_lang_Class->vftbl ==0) panic ("vftbl == 0 in use_class_as_object");*/
98                 c->header.vftbl = class_java_lang_Class->vftbl;
99                 c->classvftbl = true;
100         }
101 }
102
103
104 /************************** tables for methods ********************************/
105
106 #undef JOWENN_DEBUG
107 #undef JOWENN_DEBUG1
108
109 #ifdef STATIC_CLASSPATH
110 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
111
112 /* table for fast string comparison */
113 static nativecompref nativecomptable[NATIVETABLESIZE];
114
115 /* string comparsion table initialized */
116 static bool nativecompdone = false;
117 #endif
118
119
120 /* XXX don't define this in a header file!!! */
121
122 static struct nativeCall nativeCalls[] =
123 {
124 #include "nativecalls.inc"
125 };
126
127 #define NATIVECALLSSIZE    (sizeof(nativeCalls) / sizeof(struct nativeCall))
128
129 struct nativeCompCall nativeCompCalls[NATIVECALLSSIZE];
130
131
132 /* native_loadclasses **********************************************************
133
134    Load classes required for native methods.
135
136 *******************************************************************************/
137
138 bool native_init(void)
139 {
140 #if !defined(STATIC_CLASSPATH)
141         void *p;
142
143         /* We need to access the dummy native table, not only to remove a warning */
144         /* but to be sure that the table is not optimized away (gcc does this     */
145         /* since 3.4).                                                            */
146         p = &dummynativetable;
147 #endif
148
149         /* everything's ok */
150
151         return true;
152 }
153
154
155 /*********************** Function: native_findfunction *************************
156
157         Looks up a method (must have the same class name, method name, descriptor
158         and 'static'ness) and returns a function pointer to it.
159         Returns: function pointer or NULL (if there is no such method)
160
161         Remark: For faster operation, the names/descriptors are converted from C
162                 strings to Unicode the first time this function is called.
163
164 *******************************************************************************/
165
166 functionptr native_findfunction(utf *cname, utf *mname, 
167                                                                 utf *desc, bool isstatic)
168 {
169 #ifdef STATIC_CLASSPATH
170         int i;
171         /* entry of table for fast string comparison */
172         struct nativecompref *n;
173         /* for warning message if no function is found */
174         char *buffer;                   
175         int buffer_len;
176
177         isstatic = isstatic ? true : false;
178         
179         if (!nativecompdone) {
180                 for (i = 0; i < NATIVETABLESIZE; i++) {
181                         nativecomptable[i].classname  = 
182                                 utf_new_char(nativetable[i].classname);
183                         nativecomptable[i].methodname = 
184                                 utf_new_char(nativetable[i].methodname);
185                         nativecomptable[i].descriptor = 
186                                 utf_new_char(nativetable[i].descriptor);
187                         nativecomptable[i].isstatic   = 
188                                 nativetable[i].isstatic;
189                         nativecomptable[i].func       = 
190                                 nativetable[i].func;
191                 }
192                 nativecompdone = true;
193         }
194
195 #ifdef JOWENN_DEBUG
196         buffer_len = 
197                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
198         
199         buffer = MNEW(char, buffer_len);
200
201         strcpy(buffer, "searching matching function in native table:");
202         utf_sprint(buffer+strlen(buffer), mname);
203         strcpy(buffer+strlen(buffer), ": ");
204         utf_sprint(buffer+strlen(buffer), desc);
205         strcpy(buffer+strlen(buffer), " for class ");
206         utf_sprint(buffer+strlen(buffer), cname);
207
208         log_text(buffer);       
209
210         MFREE(buffer, char, buffer_len);
211 #endif
212                 
213         for (i = 0; i < NATIVETABLESIZE; i++) {
214                 n = &(nativecomptable[i]);
215
216                 if (cname == n->classname && mname == n->methodname &&
217                     desc == n->descriptor && isstatic == n->isstatic)
218                         return n->func;
219 #ifdef JOWENN_DEBUG
220                         else {
221                                 if (cname == n->classname && mname == n->methodname )  log_text("static and descriptor mismatch");
222                         
223                                 else {
224                                         buffer_len = 
225                                           utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
226         
227                                         buffer = MNEW(char, buffer_len);
228
229                                         strcpy(buffer, "comparing with:");
230                                         utf_sprint(buffer+strlen(buffer), n->methodname);
231                                         strcpy (buffer+strlen(buffer), ": ");
232                                         utf_sprint(buffer+strlen(buffer), n->descriptor);
233                                         strcpy(buffer+strlen(buffer), " for class ");
234                                         utf_sprint(buffer+strlen(buffer), n->classname);
235
236                                         log_text(buffer);       
237
238                                         MFREE(buffer, char, buffer_len);
239                                 }
240                         } 
241 #endif
242         }
243
244                 
245         /* no function was found, display warning */
246
247         buffer_len = 
248                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
249
250         buffer = MNEW(char, buffer_len);
251
252         strcpy(buffer, "warning: native function ");
253         utf_sprint(buffer + strlen(buffer), mname);
254         strcpy(buffer + strlen(buffer), ": ");
255         utf_sprint(buffer + strlen(buffer), desc);
256         strcpy(buffer + strlen(buffer), " not found in class ");
257         utf_sprint(buffer + strlen(buffer), cname);
258
259         log_text(buffer);       
260
261         MFREE(buffer, char, buffer_len);
262
263 /*      exit(1); */
264
265         /* keep compiler happy */
266         return NULL;
267 #else
268 /* dynamic classpath */
269   return 0;
270 #endif
271 }
272
273
274 /****************** function class_findfield_approx ****************************
275         
276         searches in 'classinfo'-structure for a field with the
277         specified name
278
279 *******************************************************************************/
280  
281 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
282 {
283         s4 i;
284
285         for (i = 0; i < c->fieldscount; i++) {
286                 /* compare field names */
287                 if ((c->fields[i].name == name))
288                         return &(c->fields[i]);
289         }
290
291         /* field was not found, raise exception */      
292         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
293
294         return NULL;
295 }
296
297
298 s4 class_findfield_index_approx(classinfo *c, utf *name)
299 {
300         s4 i;
301
302         for (i = 0; i < c->fieldscount; i++) {
303                 /* compare field names */
304                 if ((c->fields[i].name == name))
305                         return i;
306         }
307
308         /* field was not found, raise exception */      
309         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
310
311         return -1;
312 }
313
314
315 /* native_new_and_init *********************************************************
316
317    Creates a new object on the heap and calls the initializer.
318    Returns the object pointer or NULL if memory is exhausted.
319                         
320 *******************************************************************************/
321
322 java_objectheader *native_new_and_init(classinfo *c)
323 {
324         methodinfo *m;
325         java_objectheader *o;
326
327         if (!c)
328                 return *exceptionptr;
329
330         /* create object */
331
332         o = builtin_new(c);
333         
334         if (!o)
335                 return NULL;
336
337         /* find initializer */
338
339         m = class_findmethod(c, utf_init, utf_void__void);
340                                                       
341         /* initializer not found */
342
343         if (!m)
344                 return o;
345
346         /* call initializer */
347
348         asm_calljavafunction(m, o, NULL, NULL, NULL);
349
350         return o;
351 }
352
353
354 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
355 {
356         methodinfo *m;
357         java_objectheader *o;
358
359         if (!c)
360                 return *exceptionptr;
361
362         /* create object */
363
364         o = builtin_new(c);
365
366         if (!o)
367                 return NULL;
368
369         /* find initializer */
370
371         m = class_resolveclassmethod(c,
372                                                                  utf_init,
373                                                                  utf_java_lang_String__void,
374                                                                  NULL,
375                                                                  true);
376
377         /* initializer not found */
378
379         if (!m)
380                 return NULL;
381
382         /* call initializer */
383
384         asm_calljavafunction(m, o, s, NULL, NULL);
385
386         return o;
387 }
388
389
390 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
391 {
392         methodinfo *m;
393         java_objectheader *o;
394
395         if (!c)
396                 return *exceptionptr;
397
398         /* create object */
399
400         o = builtin_new(c);
401         
402         if (!o)
403                 return NULL;
404
405         /* find initializer */
406
407         m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
408
409         /* initializer not found  */
410
411         if (!m)
412                 return NULL;
413
414         /* call initializer */
415
416         asm_calljavafunction(m, o, (void *) (ptrint) i, NULL, NULL);
417
418         return o;
419 }
420
421
422 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
423 {
424         methodinfo *m;
425         java_objectheader *o;
426
427         if (!c)
428                 return *exceptionptr;
429
430         /* create object */
431
432         o = builtin_new(c);
433         
434         if (!o)
435                 return NULL;
436
437         /* find initializer */
438
439         m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
440                                                       
441         /* initializer not found */
442
443         if (!m)
444                 return NULL;
445
446         /* call initializer */
447
448         asm_calljavafunction(m, o, t, NULL, NULL);
449
450         return o;
451 }
452
453
454 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
455 {
456     *dest = src;
457 #if 0
458     /* XXX this kind of copying does not work (in the general
459      * case). The interface tables would have to be copied, too. I
460      * don't see why we should make a copy anyway. -Edwin
461      */
462         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
463         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
464         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
465 #endif
466 }
467
468
469 /******************************************************************************************                                                                                                             
470
471         creates method signature (excluding return type) from array of 
472         class-objects representing the parameters of the method 
473
474 *******************************************************************************************/
475
476
477 utf *create_methodsig(java_objectarray* types, char *retType)
478 {
479     char *buffer;       /* buffer for building the desciptor */
480     char *pos;          /* current position in buffer */
481     utf *result;        /* the method signature */
482     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
483     u4 i, j;
484  
485     if (!types) return NULL;
486
487     /* determine required buffer-size */    
488     for (i = 0; i < types->header.size; i++) {
489                 classinfo *c = (classinfo *) types->data[i];
490                 buffer_size  = buffer_size + c->name->blength + 2;
491     }
492
493     if (retType) buffer_size += strlen(retType);
494
495     /* allocate buffer */
496     buffer = MNEW(char, buffer_size);
497     pos    = buffer;
498     
499     /* method-desciptor starts with parenthesis */
500     *pos++ = '(';
501
502     for (i = 0; i < types->header.size; i++) {
503                 char ch;           
504
505                 /* current argument */
506             classinfo *c = (classinfo *) types->data[i];
507
508             /* current position in utf-text */
509             char *utf_ptr = c->name->text; 
510             
511             /* determine type of argument */
512             if ((ch = utf_nextu2(&utf_ptr)) == '[') {
513                 /* arrayclass */
514                 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
515                                 *pos++ = *utf_ptr; /* copy text */
516                         }
517
518             } else {            
519                         /* check for primitive types */
520                         for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
521                                 char *utf_pos   = utf_ptr - 1;
522                                 char *primitive = primitivetype_table[j].wrapname;
523
524                                 /* compare text */
525                                 while (utf_pos < utf_end(c->name)) {
526                                         if (*utf_pos++ != *primitive++) goto nomatch;
527                                 }
528
529                                 /* primitive type found */
530                                 *pos++ = primitivetype_table[j].typesig;
531                                 goto next_type;
532
533                         nomatch:
534                                 ;
535                         }
536
537                         /* no primitive type and no arrayclass, so must be object */
538                         *pos++ = 'L';
539
540                         /* copy text */
541                         for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
542                                 *pos++ = *utf_ptr;
543                         }
544
545                         *pos++ = ';';
546
547                 next_type:
548                         ;
549                 }  
550     }       
551
552     *pos++ = ')';
553
554     if (retType) {
555                 for (i = 0; i < strlen(retType); i++) {
556                         *pos++ = retType[i];
557                 }
558     }
559
560     /* create utf-string */
561     result = utf_new(buffer, (pos - buffer));
562     MFREE(buffer, char, buffer_size);
563
564     return result;
565 }
566
567
568 /******************************************************************************************
569
570         retrieve the next argument or returntype from a descriptor
571         and return the corresponding class 
572
573 *******************************************************************************************/
574
575 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
576 {
577     classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
578                                          (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
579     if (!c)
580         /* unknown type */
581         panic("illegal descriptor");
582
583     if (skip) return NULL;
584
585     use_class_as_object(c);
586     return c;
587 }
588
589
590 /* get_parametertypes **********************************************************
591
592    use the descriptor of a method to generate a java/lang/Class array
593    which contains the classes of the parametertypes of the method
594
595 *******************************************************************************/
596
597 java_objectarray* get_parametertypes(methodinfo *m) 
598 {
599     utf  *descr    =  m->descriptor;    /* method-descriptor */ 
600     char *utf_ptr  =  descr->text;      /* current position in utf-text */
601     char *desc_end =  utf_end(descr);   /* points behind utf string     */
602     java_objectarray* result;
603     int parametercount = 0;
604     int i;
605
606     /* skip '(' */
607     utf_nextu2(&utf_ptr);
608   
609     /* determine number of parameters */
610     while (*utf_ptr != ')') {
611         get_type(&utf_ptr, desc_end, true);
612                 parametercount++;
613     }
614
615     /* create class-array */
616     result = builtin_anewarray(parametercount, class_java_lang_Class);
617
618     utf_ptr = descr->text;
619     utf_nextu2(&utf_ptr);
620
621     /* get returntype classes */
622     for (i = 0; i < parametercount; i++)
623             result->data[i] =
624                         (java_objectheader *) get_type(&utf_ptr, desc_end, false);
625
626     return result;
627 }
628
629
630 /* get_exceptiontypes **********************************************************
631
632    get the exceptions which can be thrown by a method
633
634 *******************************************************************************/
635
636 java_objectarray* get_exceptiontypes(methodinfo *m)
637 {
638     u2 excount;
639     u2 i;
640     java_objectarray *result;
641
642         excount = m->thrownexceptionscount;
643
644     /* create class-array */
645     result = builtin_anewarray(excount, class_java_lang_Class);
646
647     for (i = 0; i < excount; i++) {
648                 java_objectheader *o = (java_objectheader *) (m->thrownexceptions[i]);
649                 use_class_as_object((classinfo *) o);
650                 result->data[i] = o;
651     }
652
653     return result;
654 }
655
656
657
658
659
660 /******************************************************************************************
661
662         get the returntype class of a method
663
664 *******************************************************************************************/
665
666 classinfo *get_returntype(methodinfo *m) 
667 {
668         char *utf_ptr;   /* current position in utf-text */
669         char *desc_end;  /* points behind utf string     */
670         utf *desc = m->descriptor; /* method-descriptor  */
671
672         utf_ptr  = desc->text;
673         desc_end = utf_end(desc);
674
675         /* ignore parametertypes */
676         while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
677                 /* skip */ ;
678
679         return get_type(&utf_ptr,desc_end, false);
680 }
681
682
683 /*****************************************************************************/
684 /*****************************************************************************/
685
686
687 /*--------------------------------------------------------*/
688 void printNativeCall(nativeCall nc) {
689   int i,j;
690
691   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
692   for (i=0; i<nc.methCnt; i++) {  
693       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
694
695     for (j=0; j<nc.callCnt[i]; j++) {  
696         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
697         nc.methods[i].methodCalls[j].classname, 
698         nc.methods[i].methodCalls[j].methodname, 
699         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
700       }
701     }
702   printf("-+++++--------------------\n");fflush(stdout);
703 }
704
705 /*--------------------------------------------------------*/
706 void printCompNativeCall(nativeCompCall nc) {
707   int i,j;
708   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
709   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
710   utf_display(nc.classname); fflush(stdout);
711   
712   for (i=0; i<nc.methCnt; i++) {  
713     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
714     utf_display(nc.methods[i].methodname); fflush(stdout);
715     utf_display(nc.methods[i].descriptor);fflush(stdout);
716     printf("\n");fflush(stdout);
717
718     for (j=0; j<nc.callCnt[i]; j++) {  
719       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
720         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
721         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
722         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
723         printf("\n");fflush(stdout);
724       }
725     }
726 printf("---------------------\n");fflush(stdout);
727 }
728
729
730 /*--------------------------------------------------------*/
731 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
732 {
733     int i = 0;
734     int j = 0;
735     int cnt = 0;
736     classMeth mc;
737     mc.i_class = i;
738     mc.j_method = j;
739     mc.methCnt = cnt;
740
741     return mc;
742 }
743
744 /*--------------------------------------------------------*/
745 nativeCall* findNativeClassCalls(char *aclassname ) {
746 int i;
747
748 for (i=0;i<NATIVECALLSSIZE; i++) {
749    /* convert table to utf later to speed up search */ 
750    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
751         return &nativeCalls[i];
752    }
753
754 return NULL;
755 }
756 /*--------------------------------------------------------*/
757 /*--------------------------------------------------------*/
758 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
759   int i,j;
760
761
762   ncc->classname = utf_new_char(nc.classname); 
763   ncc->methCnt = nc.methCnt;
764   
765   for (i=0; i<nc.methCnt; i++) {  
766     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
767     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
768     ncc->callCnt[i] = nc.callCnt[i];
769
770     for (j=0; j<nc.callCnt[i]; j++) {  
771
772         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
773
774         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
775           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
776           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
777           }
778         else {
779           ncc->methods[i].methodCalls[j].methodname = NULL;
780           ncc->methods[i].methodCalls[j].descriptor = NULL;
781           }
782       }
783     }
784 }
785
786
787
788 /*--------------------------------------------------------*/
789
790 bool natcall2utf(bool natcallcompdone) {
791 int i;
792
793 if (natcallcompdone) 
794         return true;
795
796 for (i=0;i<NATIVECALLSSIZE; i++) {
797    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
798    }
799
800 return true;
801 }
802
803 /*--------------------------------------------------------*/
804
805
806 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end, classinfo **start)
807 {
808 #if defined(__GNUC__)
809 #warning platform dependend
810 #endif
811         java_objectarray *tmpArray;
812         int i;
813         classinfo **current;
814         classinfo *c;
815         size_t size;
816
817         size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
818
819         /*printf("end %p, start %p, size %ld\n",end,start,size);*/
820         if (!class_java_lang_Class)
821                 class_java_lang_Class = class_new(utf_new_char("java/lang/Class"));
822
823         if (!class_java_lang_SecurityManager)
824                 class_java_lang_SecurityManager =
825                         class_new(utf_new_char("java/lang/SecurityManager"));
826
827         if (size > 0) {
828                 if (start == class_java_lang_SecurityManager) {
829                         size--;
830                         start--;
831                 }
832         }
833
834         tmpArray =
835                 builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
836
837         for(i = 0, current = start; i < size; i++, current--) {
838                 c = *current;
839                 /*              printf("%d\n",i);
840                 utf_display(c->name);*/
841                 use_class_as_object(c);
842                 tmpArray->data[i] = (java_objectheader *) c;
843         }
844
845         return tmpArray;
846 }
847
848
849 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end, classinfo **start)
850 {
851 #if defined(__GNUC__)
852 #warning platform dependend
853 #endif
854         int i;
855         classinfo **current;
856         classinfo *c;
857         classinfo *privilegedAction;
858         size_t size;
859
860         size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
861
862         /*      log_text("builtin_asm_getclassloader");
863         printf("end %p, start %p, size %ld\n",end,start,size);*/
864
865         if (!class_java_lang_SecurityManager)
866                 class_java_lang_SecurityManager =
867                         class_new(utf_new_char("java/lang/SecurityManager"));
868
869         if (size > 0) {
870                 if (start == class_java_lang_SecurityManager) {
871                         size--;
872                         start--;
873                 }
874         }
875
876         privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
877
878         for(i = 0, current = start; i < size; i++, current--) {
879                 c = *current;
880
881                 if (c == privilegedAction)
882                         return NULL;
883
884                 if (c->classloader)
885                         return (java_lang_ClassLoader *) c->classloader;
886         }
887
888         return NULL;
889 }
890
891
892 /*
893  * These are local overrides for various environment variables in Emacs.
894  * Please do not remove this and leave it at the end of the file, where
895  * Emacs will automagically detect them.
896  * ---------------------------------------------------------------------
897  * Local variables:
898  * mode: c
899  * indent-tabs-mode: t
900  * c-basic-offset: 4
901  * tab-width: 4
902  * End:
903  */