- added gnu header, emacs tailer
[cacao.git] / src / native / vm / VMThrowable.c
1 /* nat/VMThrowable.c - java/lang/Throwable
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Joseph Wenninger
28
29    $Id: VMThrowable.c 973 2004-03-25 15:19:16Z twisti $
30
31 */
32
33
34 #include "global.h"
35 #include "jni.h"
36 #include "asmpart.h"
37 #include "loader.h"
38 #include "builtin.h"
39 #include "tables.h"
40 #include "native.h"
41 #include "java_lang_Throwable.h"
42 #include "java_lang_VMThrowable.h"
43
44
45 /*
46  * Class:     java/lang/VMThrowable
47  * Method:    fillInStackTrace
48  * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable;
49  */
50 JNIEXPORT java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, jclass clazz, java_lang_Throwable *par1)
51 {
52         classinfo *class_java_lang_VMThrowable = NULL;
53         java_lang_VMThrowable *vmthrow;
54
55         if (!class_java_lang_VMThrowable)
56                 class_java_lang_VMThrowable = class_new(utf_new_char("java/lang/VMThrowable"));
57
58         if (class_java_lang_VMThrowable == NULL)
59                 panic("Needed class java.lang.VMThrowable missing");
60
61         vmthrow = (java_lang_VMThrowable *) native_new_and_init(class_java_lang_VMThrowable);
62
63         if (vmthrow == NULL)
64                 panic("Needed instance of class  java.lang.VMThrowable could not be created");
65
66 #if defined(__I386__)
67         (void) asm_get_stackTrace(&(vmthrow->vmData));
68 #else
69         vmthrow->vmData=0;
70 #endif
71
72         return vmthrow;
73 }
74
75
76
77 java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *source,long size)
78 {
79         long resultPos;
80         methodinfo *constructor;
81         classinfo *class_stacktraceelement;
82         java_objectarray *array_stacktraceelement;
83         class_stacktraceelement = (classinfo *) loader_load(utf_new_char ("java/lang/StackTraceElement"));
84
85         if (!class_stacktraceelement)
86                 return 0;
87
88
89         constructor=class_findmethod(class_stacktraceelement,utf_new_char("<init>"),
90                 utf_new_char("(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Z)V"));
91         if (!constructor)
92                 panic("java.lang.StackTraceElement misses needed constructor"); 
93
94         array_stacktraceelement = builtin_anewarray(size, class_stacktraceelement);
95
96         if (!array_stacktraceelement)
97                 return 0;
98
99 /*      printf("Should return an array with %ld element(s)\n",size);*/
100         size--;
101         
102         
103         for(resultPos=0;size>=0;resultPos++,size--) {
104                 java_objectheader *element=builtin_new(class_stacktraceelement);
105                 if (!element) {
106                         panic("Memory for stack trace element could not be allocated");
107                 }
108 #ifdef __GNUC__
109 #warning call constructor once jni is fixed to allow more than three parameters
110 #endif
111 #if 0
112                 (*env)->CallVoidMethod(env,element,constructor,
113                         javastring_new(source[size].method->class->sourcefile),
114                         source[size].linenumber,
115                         javastring_new(source[size].method->class->name),
116                         javastring_new(source[size].method->name),
117                         source[size].method->flags & ACC_NATIVE);
118 #else
119                 if (!(source[size].method->flags & ACC_NATIVE))setfield_critical(class_stacktraceelement,element,"fileName",          
120                 "Ljava/lang/String;",  jobject, 
121                 (jobject) javastring_new(source[size].method->class->sourcefile));
122                 setfield_critical(class_stacktraceelement,element,"className",          "Ljava/lang/String;",  jobject, 
123                 (jobject) javastring_new(source[size].method->class->name));
124                 setfield_critical(class_stacktraceelement,element,"methodName",          "Ljava/lang/String;",  jobject, 
125                 (jobject) javastring_new(source[size].method->name));
126                 setfield_critical(class_stacktraceelement,element,"lineNumber",          "I",  jint, 
127                 (jint) ((source[size].method->flags & ACC_NATIVE) ? -1:(source[size].linenumber)));
128                 setfield_critical(class_stacktraceelement,element,"isNative",          "Z",  jboolean, 
129                 (jboolean) ((source[size].method->flags & ACC_NATIVE) ? 1:0));
130
131
132 #endif                  
133
134                 array_stacktraceelement->data[resultPos]=element;
135         }
136
137         return array_stacktraceelement;
138
139 }
140
141
142 /*
143  * Class:     java/lang/VMThrowable
144  * Method:    getStackTrace
145  * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
146  */
147 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, java_lang_VMThrowable *this, java_lang_Throwable *par1)
148 {
149         long  pos;
150         long  maxpos;
151         utf*  classname=par1->header.vftbl->class->name;
152         utf*  init=utf_new_char("<init>");
153         utf*  throwable=utf_new_char("java/lang/Throwable");
154         stacktraceelement *el=(stacktraceelement*)this->vmData;
155
156         /*      log_text("Java_java_lang_VMThrowable_getStackTrace");
157         utf_display(par1->header.vftbl->class->name);
158         printf("\n----------------------------------------------\n");*/
159
160         if (el == 0) {
161                 return generateStackTraceArray(env, el, 0);
162         }       
163
164         for (pos = 0; el[pos].method != 0; pos++);
165
166         if (pos == 0) {
167                 panic("Stacktrace cannot have zero length");
168         }
169
170         pos--;
171         pos--;
172         maxpos = pos;
173         if (el[pos].method->class->name == throwable && el[pos].method->name == init) {
174                 for (; pos >= 0 && el[pos].method->name == init && el[pos].method->class->name != classname; pos--);
175                 pos--;
176                 if (pos < 0) {
177                         panic("Invalid stack trace for Throwable.getStackTrace()");
178                 }
179         }
180         
181         /* build the result array*/
182         pos++; /*arraysize*/
183
184         return generateStackTraceArray(env,el,pos);     
185 }
186
187
188 /*
189  * These are local overrides for various environment variables in Emacs.
190  * Please do not remove this and leave it at the end of the file, where
191  * Emacs will automagically detect them.
192  * ---------------------------------------------------------------------
193  * Local variables:
194  * mode: c
195  * indent-tabs-mode: t
196  * c-basic-offset: 4
197  * tab-width: 4
198  * End:
199  */