xref: /titanic_41/usr/src/lib/libdtrace_jni/common/dtj_util.c (revision e77b06d21580f630e0a7c437495ab283d3672828)
1fb3fb4f3Stomee /*
2fb3fb4f3Stomee  * CDDL HEADER START
3fb3fb4f3Stomee  *
4fb3fb4f3Stomee  * The contents of this file are subject to the terms of the
5fb3fb4f3Stomee  * Common Development and Distribution License (the "License").
6fb3fb4f3Stomee  * You may not use this file except in compliance with the License.
7fb3fb4f3Stomee  *
8fb3fb4f3Stomee  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fb3fb4f3Stomee  * or http://www.opensolaris.org/os/licensing.
10fb3fb4f3Stomee  * See the License for the specific language governing permissions
11fb3fb4f3Stomee  * and limitations under the License.
12fb3fb4f3Stomee  *
13fb3fb4f3Stomee  * When distributing Covered Code, include this CDDL HEADER in each
14fb3fb4f3Stomee  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fb3fb4f3Stomee  * If applicable, add the following below this CDDL HEADER, with the
16fb3fb4f3Stomee  * fields enclosed by brackets "[]" replaced with your own identifying
17fb3fb4f3Stomee  * information: Portions Copyright [yyyy] [name of copyright owner]
18fb3fb4f3Stomee  *
19fb3fb4f3Stomee  * CDDL HEADER END
20fb3fb4f3Stomee  */
21fb3fb4f3Stomee 
22fb3fb4f3Stomee /*
23*e77b06d2Stomee  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24fb3fb4f3Stomee  * Use is subject to license terms.
25fb3fb4f3Stomee  */
26fb3fb4f3Stomee 
27fb3fb4f3Stomee #pragma ident	"%Z%%M%	%I%	%E% SMI"
28fb3fb4f3Stomee 
29fb3fb4f3Stomee #include <stdlib.h>
30fb3fb4f3Stomee #include <stddef.h>
31fb3fb4f3Stomee #include <sys/types.h>
32fb3fb4f3Stomee #include <pthread.h>
33fb3fb4f3Stomee #include <string.h>
34fb3fb4f3Stomee #include <dtj_util.h>
35fb3fb4f3Stomee 
36fb3fb4f3Stomee /*
37fb3fb4f3Stomee  * dtj_util.c separates functionality that is generally useful from
38fb3fb4f3Stomee  * that which is specific to the Java DTrace API.  If moved to a separate
39fb3fb4f3Stomee  * library, this functionality could be shared by other JNI wrappers.
40fb3fb4f3Stomee  */
41fb3fb4f3Stomee 
42fb3fb4f3Stomee boolean_t g_dtj_util_debug = B_FALSE;
43fb3fb4f3Stomee static boolean_t g_dtj_load_common = B_FALSE;
44fb3fb4f3Stomee 
45fb3fb4f3Stomee /* NativeException */
46fb3fb4f3Stomee jclass g_nx_jc = 0;
47fb3fb4f3Stomee jmethodID g_nxinit_jm = 0;
48fb3fb4f3Stomee 
49fb3fb4f3Stomee /* java.io.Serializable */
50fb3fb4f3Stomee jclass g_serial_jc = 0;
51fb3fb4f3Stomee 
52fb3fb4f3Stomee /* java.lang.Number */
53fb3fb4f3Stomee jclass g_number_jc = 0;
54fb3fb4f3Stomee jmethodID g_shortval_jm = 0;
55fb3fb4f3Stomee jmethodID g_intval_jm = 0;
56fb3fb4f3Stomee jmethodID g_longval_jm = 0;
57fb3fb4f3Stomee 
58fb3fb4f3Stomee /* java.lang.Byte */
59fb3fb4f3Stomee jclass g_byte_jc = 0;
60fb3fb4f3Stomee jmethodID g_byteinit_jm = 0;
61fb3fb4f3Stomee 
62fb3fb4f3Stomee /* java.lang.Character */
63fb3fb4f3Stomee jclass g_char_jc = 0;
64fb3fb4f3Stomee jmethodID g_charinit_jm = 0;
65fb3fb4f3Stomee jmethodID g_charval_jm = 0;
66fb3fb4f3Stomee 
67fb3fb4f3Stomee /* java.lang.Short */
68fb3fb4f3Stomee jclass g_short_jc = 0;
69fb3fb4f3Stomee jmethodID g_shortinit_jm = 0;
70fb3fb4f3Stomee 
71fb3fb4f3Stomee /* java.lang.Integer */
72fb3fb4f3Stomee jclass g_int_jc = 0;
73fb3fb4f3Stomee jmethodID g_intinit_jm = 0;
74fb3fb4f3Stomee 
75fb3fb4f3Stomee /* java.lang.Long */
76fb3fb4f3Stomee jclass g_long_jc = 0;
77fb3fb4f3Stomee jmethodID g_longinit_jm = 0;
78fb3fb4f3Stomee 
79*e77b06d2Stomee /* java.math.BigInteger */
80*e77b06d2Stomee jclass g_bigint_jc = 0;
81*e77b06d2Stomee jmethodID g_bigint_val_jsm = 0;
82*e77b06d2Stomee jmethodID g_bigint_div_jm = 0;
83*e77b06d2Stomee jmethodID g_bigint_shl_jm = 0;
84*e77b06d2Stomee jmethodID g_bigint_or_jm = 0;
85*e77b06d2Stomee jmethodID g_bigint_setbit_jm = 0;
86*e77b06d2Stomee 
87fb3fb4f3Stomee /* java.lang.String */
88fb3fb4f3Stomee jclass g_string_jc = 0;
89fb3fb4f3Stomee jmethodID g_strinit_bytes_jm = 0;
90fb3fb4f3Stomee jmethodID g_strbytes_jm = 0;
91fb3fb4f3Stomee jmethodID g_trim_jm = 0;
92fb3fb4f3Stomee 
934ae67516Stomee /* java.lang.StringBuilder */
94fb3fb4f3Stomee jclass g_buf_jc = 0;
95fb3fb4f3Stomee jmethodID g_bufinit_jm = 0;
96fb3fb4f3Stomee jmethodID g_buf_append_char_jm = 0;
97fb3fb4f3Stomee jmethodID g_buf_append_int_jm = 0;
98fb3fb4f3Stomee jmethodID g_buf_append_long_jm = 0;
99fb3fb4f3Stomee jmethodID g_buf_append_str_jm = 0;
100fb3fb4f3Stomee jmethodID g_buf_append_obj_jm = 0;
101fb3fb4f3Stomee jmethodID g_buflen_jm = 0;
102fb3fb4f3Stomee jmethodID g_bufsetlen_jm = 0;
103fb3fb4f3Stomee 
104fb3fb4f3Stomee /* java.lang.Object */
105fb3fb4f3Stomee jclass g_object_jc = 0;
106fb3fb4f3Stomee jmethodID g_tostring_jm = 0;
107fb3fb4f3Stomee jmethodID g_equals_jm = 0;
108fb3fb4f3Stomee 
109fb3fb4f3Stomee /* java.lang.Enum */
110fb3fb4f3Stomee jclass g_enum_jc = 0;
111fb3fb4f3Stomee jmethodID g_enumname_jm = 0;
112fb3fb4f3Stomee 
113fb3fb4f3Stomee /* List */
114fb3fb4f3Stomee jclass g_list_jc = 0;
115fb3fb4f3Stomee jmethodID g_listclear_jm = 0;
116fb3fb4f3Stomee jmethodID g_listadd_jm = 0;
117fb3fb4f3Stomee jmethodID g_listget_jm = 0;
118fb3fb4f3Stomee jmethodID g_listsize_jm = 0;
119fb3fb4f3Stomee 
120fb3fb4f3Stomee /* Global list pools */
121fb3fb4f3Stomee static uu_list_pool_t *g_pointer_pool = NULL;
122fb3fb4f3Stomee static uu_list_pool_t *g_string_pool = NULL;
123fb3fb4f3Stomee 
124fb3fb4f3Stomee static dtj_status_t dtj_get_jni_classes(JNIEnv *, uu_list_t *, uu_list_pool_t *,
125fb3fb4f3Stomee     uu_list_pool_t *, uu_list_pool_t *, const dtj_table_entry_t *);
126fb3fb4f3Stomee static dtj_status_t dtj_cache_jni_methods(JNIEnv *, dtj_java_class_t *);
127fb3fb4f3Stomee static dtj_status_t dtj_cache_jni_fields(JNIEnv *, dtj_java_class_t *);
128fb3fb4f3Stomee 
129fb3fb4f3Stomee /* Constructors */
130fb3fb4f3Stomee static dtj_java_class_t *dtj_java_class_create(JNIEnv *, jclass *, char *,
131fb3fb4f3Stomee     uu_list_pool_t *, uu_list_pool_t *, uu_list_pool_t *);
132fb3fb4f3Stomee static dtj_java_method_t *dtj_java_method_create(JNIEnv *, jmethodID *, char *,
133fb3fb4f3Stomee     char *, uu_list_pool_t *);
134fb3fb4f3Stomee static dtj_java_method_t *dtj_java_static_method_create(JNIEnv *, jmethodID *,
135fb3fb4f3Stomee     char *, char *, uu_list_pool_t *);
136fb3fb4f3Stomee static dtj_java_field_t *dtj_java_field_create(JNIEnv *, jfieldID *, char *,
137fb3fb4f3Stomee     char *, uu_list_pool_t *);
138fb3fb4f3Stomee static dtj_java_field_t *dtj_java_static_field_create(JNIEnv *, jfieldID *,
139fb3fb4f3Stomee     char *, char *, uu_list_pool_t *);
140fb3fb4f3Stomee 
141fb3fb4f3Stomee /* Destructors */
142fb3fb4f3Stomee static void dtj_java_class_destroy(void *, void *);
143fb3fb4f3Stomee static void dtj_java_method_destroy(void *, void *);
144fb3fb4f3Stomee static void dtj_java_field_destroy(void *, void *);
145fb3fb4f3Stomee 
146fb3fb4f3Stomee /* Comparison functions, uu_compare_fn_t signature */
147fb3fb4f3Stomee static int dtj_java_class_cmp(const void *, const void *, void *);
148fb3fb4f3Stomee static int dtj_java_method_cmp(const void *, const void *, void *);
149fb3fb4f3Stomee static int dtj_java_field_cmp(const void *, const void *, void *);
150fb3fb4f3Stomee 
151fb3fb4f3Stomee /* Java Throwable */
152fb3fb4f3Stomee static void dtj_throw(JNIEnv *, jclass, const char *, va_list *);
153fb3fb4f3Stomee 
154fb3fb4f3Stomee /* Support for uu_list_t wrappers */
155fb3fb4f3Stomee static boolean_t dtj_check_pointer_pool(void);
156fb3fb4f3Stomee static boolean_t dtj_check_string_pool(void);
157fb3fb4f3Stomee 
158fb3fb4f3Stomee dtj_status_t
dtj_load_common(JNIEnv * jenv)159fb3fb4f3Stomee dtj_load_common(JNIEnv *jenv)
160fb3fb4f3Stomee {
161fb3fb4f3Stomee 	dtj_status_t status;
162fb3fb4f3Stomee 
163fb3fb4f3Stomee 	static const dtj_table_entry_t table[] = {
164fb3fb4f3Stomee 		/* NativeException */
165fb3fb4f3Stomee 		{ JCLASS,  &g_nx_jc,
166fb3fb4f3Stomee 			"org/opensolaris/os/dtrace/NativeException" },
167fb3fb4f3Stomee 		{ JMETHOD, &g_nxinit_jm, CONSTRUCTOR,
168fb3fb4f3Stomee 			"(Ljava/lang/String;ILjava/lang/Throwable;)V" },
169fb3fb4f3Stomee 
170fb3fb4f3Stomee 		/* java.io.Serializable */
171fb3fb4f3Stomee 		{ JCLASS,  &g_serial_jc, "java/io/Serializable" },
172fb3fb4f3Stomee 
173fb3fb4f3Stomee 		/* java.lang.Number */
174fb3fb4f3Stomee 		{ JCLASS,  &g_number_jc, "java/lang/Number" },
175fb3fb4f3Stomee 		{ JMETHOD, &g_shortval_jm, "shortValue", "()S" },
176fb3fb4f3Stomee 		{ JMETHOD, &g_intval_jm, "intValue", "()I" },
177fb3fb4f3Stomee 		{ JMETHOD, &g_longval_jm, "longValue", "()J" },
178fb3fb4f3Stomee 
179fb3fb4f3Stomee 		/* java.lang.Byte */
180fb3fb4f3Stomee 		{ JCLASS,  &g_byte_jc, "java/lang/Byte" },
181fb3fb4f3Stomee 		{ JMETHOD, &g_byteinit_jm, CONSTRUCTOR, "(B)V" },
182fb3fb4f3Stomee 
183fb3fb4f3Stomee 		/* java.lang.Character */
184fb3fb4f3Stomee 		{ JCLASS,  &g_char_jc, "java/lang/Character" },
185fb3fb4f3Stomee 		{ JMETHOD, &g_charinit_jm, CONSTRUCTOR, "(C)V" },
186fb3fb4f3Stomee 		{ JMETHOD, &g_charval_jm, "charValue", "()C" },
187fb3fb4f3Stomee 
188fb3fb4f3Stomee 		/* java.lang.Short */
189fb3fb4f3Stomee 		{ JCLASS,  &g_short_jc, "java/lang/Short" },
190fb3fb4f3Stomee 		{ JMETHOD, &g_shortinit_jm, CONSTRUCTOR, "(S)V" },
191fb3fb4f3Stomee 
192fb3fb4f3Stomee 		/* java.lang.Integer */
193fb3fb4f3Stomee 		{ JCLASS,  &g_int_jc, "java/lang/Integer" },
194fb3fb4f3Stomee 		{ JMETHOD, &g_intinit_jm, CONSTRUCTOR, "(I)V" },
195fb3fb4f3Stomee 
196fb3fb4f3Stomee 		/* java.lang.Long */
197fb3fb4f3Stomee 		{ JCLASS,  &g_long_jc, "java/lang/Long" },
198fb3fb4f3Stomee 		{ JMETHOD, &g_longinit_jm, CONSTRUCTOR, "(J)V" },
199fb3fb4f3Stomee 
200*e77b06d2Stomee 		/* java.math.BigInteger */
201*e77b06d2Stomee 		{ JCLASS,  &g_bigint_jc, "java/math/BigInteger" },
202*e77b06d2Stomee 		{ JMETHOD_STATIC, &g_bigint_val_jsm, "valueOf",
203*e77b06d2Stomee 			"(J)Ljava/math/BigInteger;" },
204*e77b06d2Stomee 		{ JMETHOD, &g_bigint_div_jm, "divide",
205*e77b06d2Stomee 			"(Ljava/math/BigInteger;)Ljava/math/BigInteger;" },
206*e77b06d2Stomee 		{ JMETHOD, &g_bigint_shl_jm, "shiftLeft",
207*e77b06d2Stomee 			"(I)Ljava/math/BigInteger;" },
208*e77b06d2Stomee 		{ JMETHOD, &g_bigint_or_jm, "or",
209*e77b06d2Stomee 			"(Ljava/math/BigInteger;)Ljava/math/BigInteger;" },
210*e77b06d2Stomee 		{ JMETHOD, &g_bigint_setbit_jm, "setBit",
211*e77b06d2Stomee 			"(I)Ljava/math/BigInteger;" },
212*e77b06d2Stomee 
213fb3fb4f3Stomee 		/* java.lang.String */
214fb3fb4f3Stomee 		{ JCLASS,  &g_string_jc, "java/lang/String" },
215fb3fb4f3Stomee 		{ JMETHOD, &g_strinit_bytes_jm, CONSTRUCTOR, "([B)V" },
216fb3fb4f3Stomee 		{ JMETHOD, &g_strbytes_jm, "getBytes", "()[B" },
217fb3fb4f3Stomee 		{ JMETHOD, &g_trim_jm, "trim", "()Ljava/lang/String;" },
218fb3fb4f3Stomee 
2194ae67516Stomee 		/* java.lang.StringBuilder */
2204ae67516Stomee 		{ JCLASS,  &g_buf_jc, "java/lang/StringBuilder" },
221fb3fb4f3Stomee 		{ JMETHOD, &g_bufinit_jm, CONSTRUCTOR, "()V" },
222fb3fb4f3Stomee 		{ JMETHOD, &g_buf_append_char_jm, "append",
2234ae67516Stomee 			"(C)Ljava/lang/StringBuilder;" },
224fb3fb4f3Stomee 		{ JMETHOD, &g_buf_append_int_jm, "append",
2254ae67516Stomee 			"(I)Ljava/lang/StringBuilder;" },
226fb3fb4f3Stomee 		{ JMETHOD, &g_buf_append_long_jm, "append",
2274ae67516Stomee 			"(J)Ljava/lang/StringBuilder;" },
228fb3fb4f3Stomee 		{ JMETHOD, &g_buf_append_str_jm, "append",
2294ae67516Stomee 			"(Ljava/lang/String;)Ljava/lang/StringBuilder;" },
230fb3fb4f3Stomee 		{ JMETHOD, &g_buf_append_obj_jm, "append",
2314ae67516Stomee 			"(Ljava/lang/Object;)Ljava/lang/StringBuilder;" },
232fb3fb4f3Stomee 		{ JMETHOD, &g_buflen_jm, "length", "()I" },
233fb3fb4f3Stomee 		{ JMETHOD, &g_bufsetlen_jm, "setLength", "(I)V" },
234fb3fb4f3Stomee 
235fb3fb4f3Stomee 		/* java.lang.Object */
236fb3fb4f3Stomee 		{ JCLASS,  &g_object_jc, "java/lang/Object" },
237fb3fb4f3Stomee 		{ JMETHOD, &g_tostring_jm, "toString",
238fb3fb4f3Stomee 			"()Ljava/lang/String;" },
239fb3fb4f3Stomee 		{ JMETHOD, &g_equals_jm, "equals",
240fb3fb4f3Stomee 			"(Ljava/lang/Object;)Z" },
241fb3fb4f3Stomee 
242fb3fb4f3Stomee 		/* java.lang.Enum */
243fb3fb4f3Stomee 		{ JCLASS,  &g_enum_jc, "java/lang/Enum" },
244fb3fb4f3Stomee 		{ JMETHOD, &g_enumname_jm, "name",
245fb3fb4f3Stomee 			"()Ljava/lang/String;" },
246fb3fb4f3Stomee 
247fb3fb4f3Stomee 		/* List */
248fb3fb4f3Stomee 		{ JCLASS, &g_list_jc, "java/util/List" },
249fb3fb4f3Stomee 		{ JMETHOD, &g_listclear_jm, "clear", "()V" },
250fb3fb4f3Stomee 		{ JMETHOD, &g_listadd_jm, "add", "(Ljava/lang/Object;)Z" },
251fb3fb4f3Stomee 		{ JMETHOD, &g_listget_jm, "get", "(I)Ljava/lang/Object;" },
252fb3fb4f3Stomee 		{ JMETHOD, &g_listsize_jm, "size", "()I" },
253fb3fb4f3Stomee 
254fb3fb4f3Stomee 		{ DTJ_TYPE_END }
255fb3fb4f3Stomee 	};
256fb3fb4f3Stomee 
257fb3fb4f3Stomee 	status = dtj_cache_jni_classes(jenv, table);
258fb3fb4f3Stomee 	if (status == DTJ_OK) {
259fb3fb4f3Stomee 		g_dtj_load_common = B_TRUE;
260fb3fb4f3Stomee 	}
261fb3fb4f3Stomee 	return (status);
262fb3fb4f3Stomee }
263fb3fb4f3Stomee 
264fb3fb4f3Stomee static int
265fb3fb4f3Stomee /* ARGSUSED */
dtj_java_class_cmp(const void * v1,const void * v2,void * arg)266fb3fb4f3Stomee dtj_java_class_cmp(const void * v1, const void * v2, void *arg)
267fb3fb4f3Stomee {
268fb3fb4f3Stomee 	const dtj_java_class_t *c1 = v1;
269fb3fb4f3Stomee 	const dtj_java_class_t *c2 = v2;
270fb3fb4f3Stomee 	return (strcmp(c1->djc_name, c2->djc_name));
271fb3fb4f3Stomee }
272fb3fb4f3Stomee 
273fb3fb4f3Stomee static int
274fb3fb4f3Stomee /* ARGSUSED */
dtj_java_method_cmp(const void * v1,const void * v2,void * arg)275fb3fb4f3Stomee dtj_java_method_cmp(const void *v1, const void *v2, void *arg)
276fb3fb4f3Stomee {
277fb3fb4f3Stomee 	int cmp;
278fb3fb4f3Stomee 	const dtj_java_method_t *m1 = v1;
279fb3fb4f3Stomee 	const dtj_java_method_t *m2 = v2;
280fb3fb4f3Stomee 	cmp = strcmp(m1->djm_name, m2->djm_name);
281fb3fb4f3Stomee 	if (cmp == 0) {
282fb3fb4f3Stomee 		cmp = strcmp(m1->djm_signature, m2->djm_signature);
283fb3fb4f3Stomee 	}
284fb3fb4f3Stomee 	return (cmp);
285fb3fb4f3Stomee }
286fb3fb4f3Stomee 
287fb3fb4f3Stomee static int
288fb3fb4f3Stomee /* ARGSUSED */
dtj_java_field_cmp(const void * v1,const void * v2,void * arg)289fb3fb4f3Stomee dtj_java_field_cmp(const void *v1, const void *v2, void *arg)
290fb3fb4f3Stomee {
291fb3fb4f3Stomee 	const dtj_java_field_t *f1 = v1;
292fb3fb4f3Stomee 	const dtj_java_field_t *f2 = v2;
293fb3fb4f3Stomee 	return (strcmp(f1->djf_name, f2->djf_name));
294fb3fb4f3Stomee }
295fb3fb4f3Stomee 
296fb3fb4f3Stomee static dtj_java_class_t *
dtj_java_class_create(JNIEnv * jenv,jclass * jc,char * name,uu_list_pool_t * classpool,uu_list_pool_t * methodpool,uu_list_pool_t * fieldpool)297fb3fb4f3Stomee dtj_java_class_create(JNIEnv *jenv, jclass *jc, char *name,
298fb3fb4f3Stomee     uu_list_pool_t *classpool, uu_list_pool_t *methodpool,
299fb3fb4f3Stomee     uu_list_pool_t *fieldpool)
300fb3fb4f3Stomee {
301fb3fb4f3Stomee 	dtj_java_class_t *c = uu_zalloc(sizeof (dtj_java_class_t));
302fb3fb4f3Stomee 	if (c) {
303fb3fb4f3Stomee 		uu_list_node_init(c, &c->djc_node, classpool);
304fb3fb4f3Stomee 		c->djc_ptr = jc;
305fb3fb4f3Stomee 		c->djc_name = name;
306fb3fb4f3Stomee 		c->djc_methods = uu_list_create(methodpool, NULL,
307fb3fb4f3Stomee 		    (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
308fb3fb4f3Stomee 		if (!c->djc_methods) {
309fb3fb4f3Stomee 			dtj_throw_out_of_memory(jenv,
310fb3fb4f3Stomee 			    "Failed method list creation");
311fb3fb4f3Stomee 			uu_list_node_fini(c, &c->djc_node, classpool);
312fb3fb4f3Stomee 			free(c);
313fb3fb4f3Stomee 			c = NULL;
314fb3fb4f3Stomee 		}
315fb3fb4f3Stomee 		c->djc_fields = uu_list_create(fieldpool, NULL,
316fb3fb4f3Stomee 		    (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
317fb3fb4f3Stomee 		if (!c->djc_fields) {
318fb3fb4f3Stomee 			dtj_throw_out_of_memory(jenv,
319fb3fb4f3Stomee 			    "Failed field list creation");
320fb3fb4f3Stomee 			uu_list_destroy(c->djc_methods);
321fb3fb4f3Stomee 			c->djc_methods = NULL;
322fb3fb4f3Stomee 			uu_list_node_fini(c, &c->djc_node, classpool);
323fb3fb4f3Stomee 			free(c);
324fb3fb4f3Stomee 			c = NULL;
325fb3fb4f3Stomee 		}
326fb3fb4f3Stomee 	} else {
327fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv,
328fb3fb4f3Stomee 		    "Failed to allocate class description");
329fb3fb4f3Stomee 	}
330fb3fb4f3Stomee 	return (c);
331fb3fb4f3Stomee }
332fb3fb4f3Stomee 
333fb3fb4f3Stomee static dtj_java_method_t *
dtj_java_method_create(JNIEnv * jenv,jmethodID * jm,char * name,char * signature,uu_list_pool_t * methodpool)334fb3fb4f3Stomee dtj_java_method_create(JNIEnv *jenv, jmethodID *jm, char *name, char *signature,
335fb3fb4f3Stomee     uu_list_pool_t *methodpool)
336fb3fb4f3Stomee {
337fb3fb4f3Stomee 	dtj_java_method_t *m = uu_zalloc(sizeof (dtj_java_method_t));
338fb3fb4f3Stomee 	if (m) {
339fb3fb4f3Stomee 		uu_list_node_init(m, &m->djm_node, methodpool);
340fb3fb4f3Stomee 		m->djm_ptr = jm;
341fb3fb4f3Stomee 		m->djm_name = name;
342fb3fb4f3Stomee 		m->djm_signature = signature;
343fb3fb4f3Stomee 		m->djm_static = B_FALSE;
344fb3fb4f3Stomee 	} else {
345fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv,
346fb3fb4f3Stomee 		    "Failed to allocate method description");
347fb3fb4f3Stomee 	}
348fb3fb4f3Stomee 	return (m);
349fb3fb4f3Stomee }
350fb3fb4f3Stomee 
351fb3fb4f3Stomee static dtj_java_method_t *
dtj_java_static_method_create(JNIEnv * jenv,jmethodID * jm,char * name,char * signature,uu_list_pool_t * methodpool)352fb3fb4f3Stomee dtj_java_static_method_create(JNIEnv *jenv, jmethodID *jm, char *name,
353fb3fb4f3Stomee     char *signature, uu_list_pool_t *methodpool)
354fb3fb4f3Stomee {
355fb3fb4f3Stomee 	dtj_java_method_t *m = dtj_java_method_create(jenv, jm, name, signature,
356fb3fb4f3Stomee 	    methodpool);
357fb3fb4f3Stomee 	if (m) {
358fb3fb4f3Stomee 		m->djm_static = B_TRUE;
359fb3fb4f3Stomee 	}
360fb3fb4f3Stomee 	return (m);
361fb3fb4f3Stomee }
362fb3fb4f3Stomee 
363fb3fb4f3Stomee static dtj_java_field_t *
dtj_java_field_create(JNIEnv * jenv,jfieldID * jf,char * name,char * type,uu_list_pool_t * fieldpool)364fb3fb4f3Stomee dtj_java_field_create(JNIEnv *jenv, jfieldID *jf, char *name, char *type,
365fb3fb4f3Stomee     uu_list_pool_t *fieldpool)
366fb3fb4f3Stomee {
367fb3fb4f3Stomee 	dtj_java_field_t *f = uu_zalloc(sizeof (dtj_java_field_t));
368fb3fb4f3Stomee 	if (f) {
369fb3fb4f3Stomee 		uu_list_node_init(f, &f->djf_node, fieldpool);
370fb3fb4f3Stomee 		f->djf_ptr = jf;
371fb3fb4f3Stomee 		f->djf_name = name;
372fb3fb4f3Stomee 		f->djf_type = type;
373fb3fb4f3Stomee 		f->djf_static = B_FALSE;
374fb3fb4f3Stomee 	} else {
375fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv,
376fb3fb4f3Stomee 		    "Failed to allocate field description");
377fb3fb4f3Stomee 	}
378fb3fb4f3Stomee 	return (f);
379fb3fb4f3Stomee }
380fb3fb4f3Stomee 
381fb3fb4f3Stomee static dtj_java_field_t *
dtj_java_static_field_create(JNIEnv * jenv,jfieldID * jf,char * name,char * type,uu_list_pool_t * fieldpool)382fb3fb4f3Stomee dtj_java_static_field_create(JNIEnv *jenv, jfieldID *jf, char *name, char *type,
383fb3fb4f3Stomee     uu_list_pool_t *fieldpool)
384fb3fb4f3Stomee {
385fb3fb4f3Stomee 	dtj_java_field_t *f = dtj_java_field_create(jenv, jf, name, type,
386fb3fb4f3Stomee 	    fieldpool);
387fb3fb4f3Stomee 	if (f) {
388fb3fb4f3Stomee 		f->djf_static = B_TRUE;
389fb3fb4f3Stomee 	}
390fb3fb4f3Stomee 	return (f);
391fb3fb4f3Stomee }
392fb3fb4f3Stomee 
393fb3fb4f3Stomee static void
394fb3fb4f3Stomee /* ARGSUSED */
dtj_java_class_destroy(void * v,void * arg)395fb3fb4f3Stomee dtj_java_class_destroy(void *v, void *arg)
396fb3fb4f3Stomee {
397fb3fb4f3Stomee 	if (v) {
398fb3fb4f3Stomee 		dtj_java_class_t *c = v;
399fb3fb4f3Stomee 		c->djc_ptr = NULL;  /* do not free user-defined storage */
400fb3fb4f3Stomee 		c->djc_name = NULL; /* string literal */
401fb3fb4f3Stomee 		dtj_list_destroy(c->djc_methods, dtj_java_method_destroy, NULL);
402fb3fb4f3Stomee 		dtj_list_destroy(c->djc_fields, dtj_java_field_destroy, NULL);
403fb3fb4f3Stomee 		c->djc_methods = NULL;
404fb3fb4f3Stomee 		c->djc_fields = NULL;
405fb3fb4f3Stomee 		uu_free(v);
406fb3fb4f3Stomee 	}
407fb3fb4f3Stomee }
408fb3fb4f3Stomee 
409fb3fb4f3Stomee static void
410fb3fb4f3Stomee /* ARGSUSED */
dtj_java_method_destroy(void * v,void * arg)411fb3fb4f3Stomee dtj_java_method_destroy(void *v, void *arg)
412fb3fb4f3Stomee {
413fb3fb4f3Stomee 	if (v) {
414fb3fb4f3Stomee 		dtj_java_method_t *m = v;
415fb3fb4f3Stomee 		m->djm_ptr = NULL;	/* do not free user-defined space */
416fb3fb4f3Stomee 		m->djm_name = NULL;	/* string literal */
417fb3fb4f3Stomee 		m->djm_signature = NULL;	/* string literal */
418fb3fb4f3Stomee 		uu_free(v);
419fb3fb4f3Stomee 	}
420fb3fb4f3Stomee }
421fb3fb4f3Stomee 
422fb3fb4f3Stomee static void
423fb3fb4f3Stomee /* ARGSUSED */
dtj_java_field_destroy(void * v,void * arg)424fb3fb4f3Stomee dtj_java_field_destroy(void *v, void *arg)
425fb3fb4f3Stomee {
426fb3fb4f3Stomee 	if (v) {
427fb3fb4f3Stomee 		dtj_java_field_t *f = v;
428fb3fb4f3Stomee 		f->djf_ptr = NULL;  /* do not free user-defined space */
429fb3fb4f3Stomee 		f->djf_name = NULL; /* string literal */
430fb3fb4f3Stomee 		f->djf_type = NULL; /* string literal */
431fb3fb4f3Stomee 		uu_free(f);
432fb3fb4f3Stomee 	}
433fb3fb4f3Stomee }
434fb3fb4f3Stomee 
435fb3fb4f3Stomee dtj_status_t
dtj_cache_jni_classes(JNIEnv * jenv,const dtj_table_entry_t * table)436fb3fb4f3Stomee dtj_cache_jni_classes(JNIEnv *jenv, const dtj_table_entry_t *table)
437fb3fb4f3Stomee {
438fb3fb4f3Stomee 	dtj_java_class_t *class;
439fb3fb4f3Stomee 	uu_list_pool_t *classpool;
440fb3fb4f3Stomee 	uu_list_pool_t *methodpool;
441fb3fb4f3Stomee 	uu_list_pool_t *fieldpool;
442fb3fb4f3Stomee 	uu_list_t *classes;
443fb3fb4f3Stomee 	uu_list_walk_t *itr;
444fb3fb4f3Stomee 	jclass jc;
445fb3fb4f3Stomee 	jclass gjc;
446fb3fb4f3Stomee 	dtj_status_t status;
447fb3fb4f3Stomee 
448fb3fb4f3Stomee 	classpool = uu_list_pool_create("classpool",
449fb3fb4f3Stomee 	    sizeof (dtj_java_class_t),
450fb3fb4f3Stomee 	    offsetof(dtj_java_class_t, djc_node), dtj_java_class_cmp,
451fb3fb4f3Stomee 	    (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
452fb3fb4f3Stomee 	if (!classpool) {
453fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv, "failed class pool creation");
454fb3fb4f3Stomee 		return (DTJ_ERR);
455fb3fb4f3Stomee 	}
456fb3fb4f3Stomee 	methodpool = uu_list_pool_create("methodpool",
457fb3fb4f3Stomee 	    sizeof (dtj_java_method_t),
458fb3fb4f3Stomee 	    offsetof(dtj_java_method_t, djm_node), dtj_java_method_cmp,
459fb3fb4f3Stomee 	    (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
460fb3fb4f3Stomee 	if (!methodpool) {
461fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv, "failed method pool creation");
462fb3fb4f3Stomee 		return (DTJ_ERR);
463fb3fb4f3Stomee 	}
464fb3fb4f3Stomee 	fieldpool = uu_list_pool_create("fieldpool",
465fb3fb4f3Stomee 	    sizeof (dtj_java_field_t),
466fb3fb4f3Stomee 	    offsetof(dtj_java_field_t, djf_node), dtj_java_field_cmp,
467fb3fb4f3Stomee 	    (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
468fb3fb4f3Stomee 	if (!fieldpool) {
469fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv, "failed field pool creation");
470fb3fb4f3Stomee 		return (DTJ_ERR);
471fb3fb4f3Stomee 	}
472fb3fb4f3Stomee 
473fb3fb4f3Stomee 	classes = uu_list_create(classpool, NULL,
474fb3fb4f3Stomee 	    (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
475fb3fb4f3Stomee 	if (!classes) {
476fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv, "failed class list creation");
477fb3fb4f3Stomee 		return (DTJ_ERR);
478fb3fb4f3Stomee 	}
479fb3fb4f3Stomee 
480fb3fb4f3Stomee 	status = dtj_get_jni_classes(jenv, classes, classpool, methodpool,
481fb3fb4f3Stomee 	    fieldpool, table);
482fb3fb4f3Stomee 	if (status != DTJ_OK) {
483fb3fb4f3Stomee 		/* java error pending */
484fb3fb4f3Stomee 		return (status);
485fb3fb4f3Stomee 	}
486fb3fb4f3Stomee 
487fb3fb4f3Stomee 	itr = uu_list_walk_start(classes, 0);
488fb3fb4f3Stomee 	while ((class = uu_list_walk_next(itr)) != NULL) {
489fb3fb4f3Stomee 		jc = (*jenv)->FindClass(jenv, class->djc_name);
490fb3fb4f3Stomee 		if (!jc) {
491fb3fb4f3Stomee 			/* NoClassDefFoundError pending */
492fb3fb4f3Stomee 			return (DTJ_ERR);
493fb3fb4f3Stomee 		}
494fb3fb4f3Stomee 		gjc = (*jenv)->NewGlobalRef(jenv, jc);
495fb3fb4f3Stomee 		(*jenv)->DeleteLocalRef(jenv, jc);
496fb3fb4f3Stomee 		if (!gjc) {
497fb3fb4f3Stomee 			dtj_throw_out_of_memory(jenv,
498fb3fb4f3Stomee 			    "Failed to create global class reference");
499fb3fb4f3Stomee 			return (DTJ_ERR);
500fb3fb4f3Stomee 		}
501fb3fb4f3Stomee 		*(class->djc_ptr) = gjc;
502fb3fb4f3Stomee 		status = dtj_cache_jni_methods(jenv, class);
503fb3fb4f3Stomee 		if (status != DTJ_OK) {
504fb3fb4f3Stomee 			/* java error pending */
505fb3fb4f3Stomee 			return (status);
506fb3fb4f3Stomee 		}
507fb3fb4f3Stomee 		status = dtj_cache_jni_fields(jenv, class);
508fb3fb4f3Stomee 		if (status != DTJ_OK) {
509fb3fb4f3Stomee 			/* java error pending */
510fb3fb4f3Stomee 			return (status);
511fb3fb4f3Stomee 		}
512fb3fb4f3Stomee 	}
513fb3fb4f3Stomee 	uu_list_walk_end(itr);
514fb3fb4f3Stomee 	dtj_list_destroy(classes, dtj_java_class_destroy, NULL);
515fb3fb4f3Stomee 	uu_list_pool_destroy(classpool);
516fb3fb4f3Stomee 	uu_list_pool_destroy(methodpool);
517fb3fb4f3Stomee 	uu_list_pool_destroy(fieldpool);
518fb3fb4f3Stomee 	return (DTJ_OK);
519fb3fb4f3Stomee }
520fb3fb4f3Stomee 
521fb3fb4f3Stomee /*
522fb3fb4f3Stomee  * Converts JNI table entry desriptions into java_class_t descriptors.
523fb3fb4f3Stomee  */
524fb3fb4f3Stomee static dtj_status_t
dtj_get_jni_classes(JNIEnv * jenv,uu_list_t * classes,uu_list_pool_t * classpool,uu_list_pool_t * methodpool,uu_list_pool_t * fieldpool,const dtj_table_entry_t * table)525fb3fb4f3Stomee dtj_get_jni_classes(JNIEnv *jenv, uu_list_t *classes,
526fb3fb4f3Stomee     uu_list_pool_t *classpool, uu_list_pool_t *methodpool,
527fb3fb4f3Stomee     uu_list_pool_t *fieldpool, const dtj_table_entry_t *table)
528fb3fb4f3Stomee {
529fb3fb4f3Stomee 	int i;
530fb3fb4f3Stomee 	dtj_java_class_t *c = NULL;
531fb3fb4f3Stomee 	dtj_java_method_t *m;
532fb3fb4f3Stomee 	dtj_java_field_t *f;
533fb3fb4f3Stomee 
534fb3fb4f3Stomee 	for (i = 0; table[i].djte_type != DTJ_TYPE_END; ++i) {
535fb3fb4f3Stomee 		/*
536fb3fb4f3Stomee 		 * Class not added until all of its method and field information
537fb3fb4f3Stomee 		 * is attached, so we defer adding a class until the next
538fb3fb4f3Stomee 		 * element with type JCLASS.
539fb3fb4f3Stomee 		 */
540fb3fb4f3Stomee 		switch (table[i].djte_type) {
541fb3fb4f3Stomee 		case JCLASS:
542fb3fb4f3Stomee 			if (c) {
543fb3fb4f3Stomee 				/* previous class */
544fb3fb4f3Stomee 				if (!dtj_list_add(classes, c)) {
545fb3fb4f3Stomee 					dtj_throw_out_of_memory(jenv,
546fb3fb4f3Stomee 					    "Failed to add class description");
547fb3fb4f3Stomee 					/*
548fb3fb4f3Stomee 					 * In response to an error return value,
549fb3fb4f3Stomee 					 * the caller will delete the class
550fb3fb4f3Stomee 					 * descriptions list with any
551fb3fb4f3Stomee 					 * descriptions created so far.
552fb3fb4f3Stomee 					 */
553fb3fb4f3Stomee 					return (DTJ_ERR);
554fb3fb4f3Stomee 				}
555fb3fb4f3Stomee 			}
556fb3fb4f3Stomee 			c = dtj_java_class_create(jenv,
557fb3fb4f3Stomee 			    (jclass *)table[i].djte_addr, table[i].djte_name,
558fb3fb4f3Stomee 			    classpool, methodpool, fieldpool);
559fb3fb4f3Stomee 			if (!c) {
560fb3fb4f3Stomee 				/* OutOfMemoryError pending */
561fb3fb4f3Stomee 				return (DTJ_ERR);
562fb3fb4f3Stomee 			}
563fb3fb4f3Stomee 			break;
564fb3fb4f3Stomee 		case JMETHOD:
565fb3fb4f3Stomee 			if (!c) {
566fb3fb4f3Stomee 				dtj_throw_illegal_state(jenv,
567fb3fb4f3Stomee 				    "method description not preceded "
568fb3fb4f3Stomee 				    "by class description");
569fb3fb4f3Stomee 				return (DTJ_ERR);
570fb3fb4f3Stomee 			}
571fb3fb4f3Stomee 			m = dtj_java_method_create(jenv,
572fb3fb4f3Stomee 			    (jmethodID *)table[i].djte_addr,
573fb3fb4f3Stomee 			    table[i].djte_name, table[i].djte_desc,
574fb3fb4f3Stomee 			    methodpool);
575fb3fb4f3Stomee 			if (!m) {
576fb3fb4f3Stomee 				/* OutOfMemoryError pending */
577fb3fb4f3Stomee 				return (DTJ_ERR);
578fb3fb4f3Stomee 			}
579fb3fb4f3Stomee 			if (!dtj_list_add(c->djc_methods, m)) {
580fb3fb4f3Stomee 				dtj_throw_out_of_memory(jenv,
581fb3fb4f3Stomee 				    "Failed to add method description");
582fb3fb4f3Stomee 				return (DTJ_ERR);
583fb3fb4f3Stomee 			}
584fb3fb4f3Stomee 			break;
585fb3fb4f3Stomee 		case JMETHOD_STATIC:
586fb3fb4f3Stomee 			if (!c) {
587fb3fb4f3Stomee 				dtj_throw_illegal_state(jenv,
588fb3fb4f3Stomee 				    "static method description not preceded "
589fb3fb4f3Stomee 				    "by class description");
590fb3fb4f3Stomee 				return (DTJ_ERR);
591fb3fb4f3Stomee 			}
592fb3fb4f3Stomee 			m = dtj_java_static_method_create(jenv,
593fb3fb4f3Stomee 			    (jmethodID *)table[i].djte_addr,
594fb3fb4f3Stomee 			    table[i].djte_name, table[i].djte_desc,
595fb3fb4f3Stomee 			    methodpool);
596fb3fb4f3Stomee 			if (!m) {
597fb3fb4f3Stomee 				/* OutOfMemoryError pending */
598fb3fb4f3Stomee 				return (DTJ_ERR);
599fb3fb4f3Stomee 			}
600fb3fb4f3Stomee 			if (!dtj_list_add(c->djc_methods, m)) {
601fb3fb4f3Stomee 				dtj_throw_out_of_memory(jenv,
602fb3fb4f3Stomee 				    "Failed to add static method description");
603fb3fb4f3Stomee 				return (DTJ_ERR);
604fb3fb4f3Stomee 			}
605fb3fb4f3Stomee 			break;
606fb3fb4f3Stomee 		case JFIELD:
607fb3fb4f3Stomee 			if (!c) {
608fb3fb4f3Stomee 				dtj_throw_illegal_state(jenv,
609fb3fb4f3Stomee 				    "field description not preceded "
610fb3fb4f3Stomee 				    "by class description");
611fb3fb4f3Stomee 				return (DTJ_ERR);
612fb3fb4f3Stomee 			}
613fb3fb4f3Stomee 			f = dtj_java_field_create(jenv,
614fb3fb4f3Stomee 			    (jfieldID *)table[i].djte_addr,
615fb3fb4f3Stomee 			    table[i].djte_name, table[i].djte_desc,
616fb3fb4f3Stomee 			    fieldpool);
617fb3fb4f3Stomee 			if (!f) {
618fb3fb4f3Stomee 				/* OutOfMemoryError pending */
619fb3fb4f3Stomee 				return (DTJ_ERR);
620fb3fb4f3Stomee 			}
621fb3fb4f3Stomee 			if (!dtj_list_add(c->djc_fields, f)) {
622fb3fb4f3Stomee 				dtj_throw_out_of_memory(jenv,
623fb3fb4f3Stomee 				    "Failed to add field description");
624fb3fb4f3Stomee 				return (DTJ_ERR);
625fb3fb4f3Stomee 			}
626fb3fb4f3Stomee 			break;
627fb3fb4f3Stomee 		case JFIELD_STATIC:
628fb3fb4f3Stomee 			if (!c) {
629fb3fb4f3Stomee 				dtj_throw_illegal_state(jenv,
630fb3fb4f3Stomee 				    "static field description not preceded "
631fb3fb4f3Stomee 				    "by class description");
632fb3fb4f3Stomee 				return (DTJ_ERR);
633fb3fb4f3Stomee 			}
634fb3fb4f3Stomee 			f = dtj_java_static_field_create(jenv,
635fb3fb4f3Stomee 			    (jfieldID *)table[i].djte_addr,
636fb3fb4f3Stomee 			    table[i].djte_name, table[i].djte_desc,
637fb3fb4f3Stomee 			    fieldpool);
638fb3fb4f3Stomee 			if (!f) {
639fb3fb4f3Stomee 				/* OutOfMemoryError pending */
640fb3fb4f3Stomee 				return (DTJ_ERR);
641fb3fb4f3Stomee 			}
642fb3fb4f3Stomee 			if (!dtj_list_add(c->djc_fields, f)) {
643fb3fb4f3Stomee 				dtj_throw_out_of_memory(jenv,
644fb3fb4f3Stomee 				    "Failed to add static field description");
645fb3fb4f3Stomee 				return (DTJ_ERR);
646fb3fb4f3Stomee 			}
647fb3fb4f3Stomee 			break;
648fb3fb4f3Stomee 		default:
649fb3fb4f3Stomee 			dtj_throw_illegal_state(jenv,
650fb3fb4f3Stomee 			    "Unexpected jni_type_e: %d", table[i].djte_type);
651fb3fb4f3Stomee 			return (DTJ_ERR);
652fb3fb4f3Stomee 		}
653fb3fb4f3Stomee 	}
654fb3fb4f3Stomee 	if (c) {
655fb3fb4f3Stomee 		/* last class */
656fb3fb4f3Stomee 		if (!dtj_list_add(classes, c)) {
657fb3fb4f3Stomee 			dtj_throw_out_of_memory(jenv,
658fb3fb4f3Stomee 			    "Failed to add class description");
659fb3fb4f3Stomee 			return (DTJ_ERR);
660fb3fb4f3Stomee 		}
661fb3fb4f3Stomee 	}
662fb3fb4f3Stomee 
663fb3fb4f3Stomee 	return (DTJ_OK);
664fb3fb4f3Stomee }
665fb3fb4f3Stomee 
666fb3fb4f3Stomee static dtj_status_t
dtj_cache_jni_methods(JNIEnv * jenv,dtj_java_class_t * c)667fb3fb4f3Stomee dtj_cache_jni_methods(JNIEnv *jenv, dtj_java_class_t *c)
668fb3fb4f3Stomee {
669fb3fb4f3Stomee 	dtj_java_method_t *method;
670fb3fb4f3Stomee 	jmethodID jm;
671fb3fb4f3Stomee 	uu_list_walk_t *itr;
672fb3fb4f3Stomee 	itr = uu_list_walk_start(c->djc_methods, 0);
673fb3fb4f3Stomee 	while ((method = uu_list_walk_next(itr)) != NULL) {
674fb3fb4f3Stomee 		if (method->djm_static) {
675fb3fb4f3Stomee 			jm = (*jenv)->GetStaticMethodID(jenv, *(c->djc_ptr),
676fb3fb4f3Stomee 			    method->djm_name, method->djm_signature);
677fb3fb4f3Stomee 		} else {
678fb3fb4f3Stomee 			jm = (*jenv)->GetMethodID(jenv, *(c->djc_ptr),
679fb3fb4f3Stomee 			    method->djm_name, method->djm_signature);
680fb3fb4f3Stomee 		}
681fb3fb4f3Stomee 		if (jm == 0) {
682fb3fb4f3Stomee 			/*
683fb3fb4f3Stomee 			 * The pending NoSuchMethodError gives only the
684fb3fb4f3Stomee 			 * method name, which is not so helpful for
685fb3fb4f3Stomee 			 * overloaded methods and methods such as <init>
686fb3fb4f3Stomee 			 * that have the same name in multiple classes.
687fb3fb4f3Stomee 			 * Clear the pending error and throw one that
688fb3fb4f3Stomee 			 * includes the class name and the method
689fb3fb4f3Stomee 			 * signature.
690fb3fb4f3Stomee 			 */
691fb3fb4f3Stomee 			jclass jc;
692fb3fb4f3Stomee 			char msg[DTJ_MSG_SIZE];
693fb3fb4f3Stomee 			(*jenv)->ExceptionClear(jenv);
694fb3fb4f3Stomee 			(void) snprintf(msg, sizeof (msg), "%s %s %s",
695fb3fb4f3Stomee 			    c->djc_name, method->djm_name,
696fb3fb4f3Stomee 			    method->djm_signature);
697fb3fb4f3Stomee 
698fb3fb4f3Stomee 			jc = (*jenv)->FindClass(jenv,
699fb3fb4f3Stomee 			    "java/lang/NoSuchMethodError");
700fb3fb4f3Stomee 			(*jenv)->ThrowNew(jenv, jc, msg);
701fb3fb4f3Stomee 			(*jenv)->DeleteLocalRef(jenv, jc);
702fb3fb4f3Stomee 			return (DTJ_ERR);
703fb3fb4f3Stomee 		}
704fb3fb4f3Stomee 		*(method->djm_ptr) = jm;
705fb3fb4f3Stomee 	}
706fb3fb4f3Stomee 	uu_list_walk_end(itr);
707fb3fb4f3Stomee 	return (DTJ_OK);
708fb3fb4f3Stomee }
709fb3fb4f3Stomee 
710fb3fb4f3Stomee static dtj_status_t
dtj_cache_jni_fields(JNIEnv * jenv,dtj_java_class_t * c)711fb3fb4f3Stomee dtj_cache_jni_fields(JNIEnv *jenv, dtj_java_class_t *c)
712fb3fb4f3Stomee {
713fb3fb4f3Stomee 	dtj_java_field_t *field;
714fb3fb4f3Stomee 	jfieldID jf;
715fb3fb4f3Stomee 	uu_list_walk_t *itr;
716fb3fb4f3Stomee 	itr = uu_list_walk_start(c->djc_fields, 0);
717fb3fb4f3Stomee 	while ((field = uu_list_walk_next(itr)) != NULL) {
718fb3fb4f3Stomee 		if (field->djf_static) {
719fb3fb4f3Stomee 			jf = (*jenv)->GetStaticFieldID(jenv, *(c->djc_ptr),
720fb3fb4f3Stomee 			    field->djf_name, field->djf_type);
721fb3fb4f3Stomee 		} else {
722fb3fb4f3Stomee 			jf = (*jenv)->GetFieldID(jenv, *(c->djc_ptr),
723fb3fb4f3Stomee 			    field->djf_name, field->djf_type);
724fb3fb4f3Stomee 		}
725fb3fb4f3Stomee 		if (jf == 0) {
726fb3fb4f3Stomee 			jclass jc;
727fb3fb4f3Stomee 			char msg[DTJ_MSG_SIZE];
728fb3fb4f3Stomee 			(*jenv)->ExceptionClear(jenv);
729fb3fb4f3Stomee 			(void) snprintf(msg, sizeof (msg),
730fb3fb4f3Stomee 			    "%s.%s signature: %s", c->djc_name,
731fb3fb4f3Stomee 			    field->djf_name, field->djf_type);
732fb3fb4f3Stomee 
733fb3fb4f3Stomee 			jc = (*jenv)->FindClass(jenv,
734fb3fb4f3Stomee 			    "java/lang/NoSuchFieldError");
735fb3fb4f3Stomee 			(*jenv)->ThrowNew(jenv, jc, msg);
736fb3fb4f3Stomee 			(*jenv)->DeleteLocalRef(jenv, jc);
737fb3fb4f3Stomee 			return (DTJ_ERR);
738fb3fb4f3Stomee 		}
739fb3fb4f3Stomee 		*(field->djf_ptr) = jf;
740fb3fb4f3Stomee 	}
741fb3fb4f3Stomee 	uu_list_walk_end(itr);
742fb3fb4f3Stomee 	return (DTJ_OK);
743fb3fb4f3Stomee }
744fb3fb4f3Stomee 
745fb3fb4f3Stomee 
746fb3fb4f3Stomee /* Common utilities */
747fb3fb4f3Stomee 
748fb3fb4f3Stomee static void
dtj_throw(JNIEnv * jenv,jclass jc,const char * fmt,va_list * ap)749fb3fb4f3Stomee dtj_throw(JNIEnv *jenv, jclass jc, const char *fmt, va_list *ap)
750fb3fb4f3Stomee {
751fb3fb4f3Stomee 	char msg[DTJ_MSG_SIZE];
752fb3fb4f3Stomee 	(void) vsnprintf(msg, sizeof (msg), fmt, *ap);
753fb3fb4f3Stomee 	(*jenv)->ThrowNew(jenv, jc, msg);
754fb3fb4f3Stomee }
755fb3fb4f3Stomee 
756fb3fb4f3Stomee void
dtj_throw_out_of_memory(JNIEnv * jenv,const char * fmt,...)757fb3fb4f3Stomee dtj_throw_out_of_memory(JNIEnv *jenv, const char *fmt, ...)
758fb3fb4f3Stomee {
759fb3fb4f3Stomee 	va_list ap;
760fb3fb4f3Stomee 	jclass jc;
761fb3fb4f3Stomee 	/*
762fb3fb4f3Stomee 	 * JNI documentation unclear whether NewGlobalRef() can throw
763fb3fb4f3Stomee 	 * OutOfMemoryError, so we'll make this function safe in case
764fb3fb4f3Stomee 	 * OutOfMemoryError has already been thrown
765fb3fb4f3Stomee 	 */
766fb3fb4f3Stomee 	if ((*jenv)->ExceptionCheck(jenv)) {
767fb3fb4f3Stomee 		return;
768fb3fb4f3Stomee 	}
769fb3fb4f3Stomee 	jc = (*jenv)->FindClass(jenv,
770fb3fb4f3Stomee 	    "java/lang/OutOfMemoryError");
771fb3fb4f3Stomee 	va_start(ap, fmt);
772fb3fb4f3Stomee 	dtj_throw(jenv, jc, fmt, &ap);
773fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jc);
774fb3fb4f3Stomee 	va_end(ap);
775fb3fb4f3Stomee }
776fb3fb4f3Stomee 
777fb3fb4f3Stomee void
dtj_throw_null_pointer(JNIEnv * jenv,const char * fmt,...)778fb3fb4f3Stomee dtj_throw_null_pointer(JNIEnv *jenv, const char *fmt, ...)
779fb3fb4f3Stomee {
780fb3fb4f3Stomee 	va_list ap;
781fb3fb4f3Stomee 	jclass jc = (*jenv)->FindClass(jenv,
782fb3fb4f3Stomee 	    "java/lang/NullPointerException");
783fb3fb4f3Stomee 	va_start(ap, fmt);
784fb3fb4f3Stomee 	dtj_throw(jenv, jc, fmt, &ap);
785fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jc);
786fb3fb4f3Stomee 	va_end(ap);
787fb3fb4f3Stomee }
788fb3fb4f3Stomee 
789fb3fb4f3Stomee void
dtj_throw_illegal_state(JNIEnv * jenv,const char * fmt,...)790fb3fb4f3Stomee dtj_throw_illegal_state(JNIEnv *jenv, const char *fmt, ...)
791fb3fb4f3Stomee {
792fb3fb4f3Stomee 	va_list ap;
793fb3fb4f3Stomee 	jclass jc = (*jenv)->FindClass(jenv,
794fb3fb4f3Stomee 	    "java/lang/IllegalStateException");
795fb3fb4f3Stomee 	va_start(ap, fmt);
796fb3fb4f3Stomee 	dtj_throw(jenv, jc, fmt, &ap);
797fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jc);
798fb3fb4f3Stomee 	va_end(ap);
799fb3fb4f3Stomee }
800fb3fb4f3Stomee 
801fb3fb4f3Stomee void
dtj_throw_illegal_argument(JNIEnv * jenv,const char * fmt,...)802fb3fb4f3Stomee dtj_throw_illegal_argument(JNIEnv *jenv, const char *fmt, ...)
803fb3fb4f3Stomee {
804fb3fb4f3Stomee 	va_list ap;
805fb3fb4f3Stomee 	jclass jc = (*jenv)->FindClass(jenv,
806fb3fb4f3Stomee 	    "java/lang/IllegalArgumentException");
807fb3fb4f3Stomee 	va_start(ap, fmt);
808fb3fb4f3Stomee 	dtj_throw(jenv, jc, fmt, &ap);
809fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jc);
810fb3fb4f3Stomee 	va_end(ap);
811fb3fb4f3Stomee }
812fb3fb4f3Stomee 
813fb3fb4f3Stomee void
dtj_throw_no_such_element(JNIEnv * jenv,const char * fmt,...)814fb3fb4f3Stomee dtj_throw_no_such_element(JNIEnv *jenv, const char *fmt, ...)
815fb3fb4f3Stomee {
816fb3fb4f3Stomee 	va_list ap;
817fb3fb4f3Stomee 	jclass jc = (*jenv)->FindClass(jenv,
818fb3fb4f3Stomee 	    "java/util/NoSuchElementException");
819fb3fb4f3Stomee 	va_start(ap, fmt);
820fb3fb4f3Stomee 	dtj_throw(jenv, jc, fmt, &ap);
821fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jc);
822fb3fb4f3Stomee 	va_end(ap);
823fb3fb4f3Stomee }
824fb3fb4f3Stomee 
825fb3fb4f3Stomee void
dtj_throw_class_cast(JNIEnv * jenv,const char * fmt,...)826fb3fb4f3Stomee dtj_throw_class_cast(JNIEnv *jenv, const char *fmt, ...)
827fb3fb4f3Stomee {
828fb3fb4f3Stomee 	va_list ap;
829fb3fb4f3Stomee 	jclass jc = (*jenv)->FindClass(jenv,
830fb3fb4f3Stomee 	    "java/lang/ClassCastException");
831fb3fb4f3Stomee 	va_start(ap, fmt);
832fb3fb4f3Stomee 	dtj_throw(jenv, jc, fmt, &ap);
833fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jc);
834fb3fb4f3Stomee 	va_end(ap);
835fb3fb4f3Stomee }
836fb3fb4f3Stomee 
837fb3fb4f3Stomee void
dtj_throw_assertion(JNIEnv * jenv,const char * fmt,...)838fb3fb4f3Stomee dtj_throw_assertion(JNIEnv *jenv, const char *fmt, ...)
839fb3fb4f3Stomee {
840fb3fb4f3Stomee 	va_list ap;
841fb3fb4f3Stomee 	jclass jc = (*jenv)->FindClass(jenv,
842fb3fb4f3Stomee 	    "java/lang/AssertionError");
843fb3fb4f3Stomee 	va_start(ap, fmt);
844fb3fb4f3Stomee 	dtj_throw(jenv, jc, fmt, &ap);
845fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jc);
846fb3fb4f3Stomee 	va_end(ap);
847fb3fb4f3Stomee }
848fb3fb4f3Stomee 
849fb3fb4f3Stomee void
dtj_throw_resource_limit(JNIEnv * jenv,const char * fmt,...)850fb3fb4f3Stomee dtj_throw_resource_limit(JNIEnv *jenv, const char *fmt, ...)
851fb3fb4f3Stomee {
852fb3fb4f3Stomee 	va_list ap;
853fb3fb4f3Stomee 	jclass jc = (*jenv)->FindClass(jenv,
854fb3fb4f3Stomee 	    "org/opensolaris/os/dtrace/ResourceLimitException");
855fb3fb4f3Stomee 	va_start(ap, fmt);
856fb3fb4f3Stomee 	dtj_throw(jenv, jc, fmt, &ap);
857fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jc);
858fb3fb4f3Stomee 	va_end(ap);
859fb3fb4f3Stomee }
860fb3fb4f3Stomee 
861fb3fb4f3Stomee void
dtj_wrap_exception(JNIEnv * jenv,const char * file,int line)862fb3fb4f3Stomee dtj_wrap_exception(JNIEnv *jenv, const char *file, int line)
863fb3fb4f3Stomee {
864fb3fb4f3Stomee 	jthrowable e = NULL;
865fb3fb4f3Stomee 	jthrowable nx = NULL;
866fb3fb4f3Stomee 	jstring jfile = NULL;
867fb3fb4f3Stomee 
868fb3fb4f3Stomee 	e = (*jenv)->ExceptionOccurred(jenv);
869fb3fb4f3Stomee 	if (!e) {
870fb3fb4f3Stomee 		return;
871fb3fb4f3Stomee 	}
872fb3fb4f3Stomee 
873fb3fb4f3Stomee 	if (!g_dtj_load_common) {
874fb3fb4f3Stomee 		return;
875fb3fb4f3Stomee 	}
876fb3fb4f3Stomee 
877fb3fb4f3Stomee 	(*jenv)->ExceptionClear(jenv);
878fb3fb4f3Stomee 
879fb3fb4f3Stomee 	/* Unsafe to test while exception pending */
880fb3fb4f3Stomee 	if ((*jenv)->IsInstanceOf(jenv, e, g_nx_jc)) {
881fb3fb4f3Stomee 		/* Already wrapped */
882fb3fb4f3Stomee 		(*jenv)->Throw(jenv, e);
883fb3fb4f3Stomee 		(*jenv)->DeleteLocalRef(jenv, e);
884fb3fb4f3Stomee 		return;
885fb3fb4f3Stomee 	}
886fb3fb4f3Stomee 
887fb3fb4f3Stomee 	jfile = dtj_NewStringNative(jenv, file);
888fb3fb4f3Stomee 	if ((*jenv)->ExceptionCheck(jenv)) {
889fb3fb4f3Stomee 		/*
890fb3fb4f3Stomee 		 * Only wrap the exception if possible, otherwise just throw the
891fb3fb4f3Stomee 		 * original exception.
892fb3fb4f3Stomee 		 */
893fb3fb4f3Stomee 		(*jenv)->ExceptionClear(jenv);
894fb3fb4f3Stomee 		(*jenv)->Throw(jenv, e);
895fb3fb4f3Stomee 		(*jenv)->DeleteLocalRef(jenv, e);
896fb3fb4f3Stomee 		return;
897fb3fb4f3Stomee 	}
898fb3fb4f3Stomee 
899fb3fb4f3Stomee 	nx = (jthrowable)(*jenv)->NewObject(jenv, g_nx_jc, g_nxinit_jm,
900fb3fb4f3Stomee 	    jfile, line, e);
901fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jfile);
902fb3fb4f3Stomee 	if ((*jenv)->ExceptionCheck(jenv)) {
903fb3fb4f3Stomee 		(*jenv)->ExceptionClear(jenv);
904fb3fb4f3Stomee 		(*jenv)->Throw(jenv, e);
905fb3fb4f3Stomee 		(*jenv)->DeleteLocalRef(jenv, e);
906fb3fb4f3Stomee 		return;
907fb3fb4f3Stomee 	}
908fb3fb4f3Stomee 
909fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, e);
910fb3fb4f3Stomee 	(*jenv)->Throw(jenv, nx);
911fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, nx);
912fb3fb4f3Stomee }
913fb3fb4f3Stomee 
914fb3fb4f3Stomee /*
915fb3fb4f3Stomee  * Calls the given java object's toString() method and prints the value to
916fb3fb4f3Stomee  * stdout.  Useful for debugging.  Guaranteed that no exception is pending when
917fb3fb4f3Stomee  * this function returns.
918fb3fb4f3Stomee  */
919fb3fb4f3Stomee void
dtj_print_object(JNIEnv * jenv,jobject jobj)920fb3fb4f3Stomee dtj_print_object(JNIEnv *jenv, jobject jobj)
921fb3fb4f3Stomee {
922fb3fb4f3Stomee 	jstring jstr;
923fb3fb4f3Stomee 	const char *cstr;
924fb3fb4f3Stomee 
925fb3fb4f3Stomee 	if (!g_dtj_load_common) {
926fb3fb4f3Stomee 		dtj_throw_illegal_state(jenv,
927fb3fb4f3Stomee 		    "dtj_load_common() has not been called");
928fb3fb4f3Stomee 		(*jenv)->ExceptionDescribe(jenv); /* clears the exception */
929fb3fb4f3Stomee 		return;
930fb3fb4f3Stomee 	}
931fb3fb4f3Stomee 
932fb3fb4f3Stomee 	if (!jobj) {
933fb3fb4f3Stomee 		(void) printf("null\n");
934fb3fb4f3Stomee 		return;
935fb3fb4f3Stomee 	}
936fb3fb4f3Stomee 
937fb3fb4f3Stomee 	jstr = (*jenv)->CallObjectMethod(jenv, jobj, g_tostring_jm);
938fb3fb4f3Stomee 	if ((*jenv)->ExceptionCheck(jenv)) {
939fb3fb4f3Stomee 		(*jenv)->ExceptionDescribe(jenv); /* clears the exception */
940fb3fb4f3Stomee 		return;
941fb3fb4f3Stomee 	}
942fb3fb4f3Stomee 	cstr = (*jenv)->GetStringUTFChars(jenv, jstr, 0);
943fb3fb4f3Stomee 	if (cstr) {
944fb3fb4f3Stomee 		(void) printf("%s\n", cstr);
945fb3fb4f3Stomee 	} else {
946fb3fb4f3Stomee 		(*jenv)->ExceptionDescribe(jenv); /* clears the exception */
947fb3fb4f3Stomee 		(*jenv)->DeleteLocalRef(jenv, jstr);
948fb3fb4f3Stomee 		return;
949fb3fb4f3Stomee 	}
950fb3fb4f3Stomee 	(*jenv)->ReleaseStringUTFChars(jenv, jstr, cstr);
951fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, jstr);
952fb3fb4f3Stomee }
953fb3fb4f3Stomee 
954*e77b06d2Stomee jobject
dtj_uint64(JNIEnv * jenv,uint64_t u)955*e77b06d2Stomee dtj_uint64(JNIEnv *jenv, uint64_t u)
956*e77b06d2Stomee {
957*e77b06d2Stomee 	int64_t i = (int64_t)u;
958*e77b06d2Stomee 	jobject val64;
959*e77b06d2Stomee 
960*e77b06d2Stomee 	if (i >= 0) {
961*e77b06d2Stomee 		val64 = (*jenv)->CallStaticObjectMethod(jenv, g_bigint_jc,
962*e77b06d2Stomee 		    g_bigint_val_jsm, u);
963*e77b06d2Stomee 	} else {
964*e77b06d2Stomee 		jobject tmp;
965*e77b06d2Stomee 
966*e77b06d2Stomee 		u ^= ((uint64_t)0x1 << 63);
967*e77b06d2Stomee 		val64 = (*jenv)->CallStaticObjectMethod(jenv, g_bigint_jc,
968*e77b06d2Stomee 		    g_bigint_val_jsm, u);
969*e77b06d2Stomee 		tmp = val64;
970*e77b06d2Stomee 		val64 = (*jenv)->CallObjectMethod(jenv, tmp,
971*e77b06d2Stomee 		    g_bigint_setbit_jm, 63);
972*e77b06d2Stomee 		(*jenv)->DeleteLocalRef(jenv, tmp);
973*e77b06d2Stomee 	}
974*e77b06d2Stomee 
975*e77b06d2Stomee 	return (val64);
976*e77b06d2Stomee }
977*e77b06d2Stomee 
978*e77b06d2Stomee jobject
dtj_int128(JNIEnv * jenv,uint64_t high,uint64_t low)979*e77b06d2Stomee dtj_int128(JNIEnv *jenv, uint64_t high, uint64_t low)
980*e77b06d2Stomee {
981*e77b06d2Stomee 	jobject val128;
982*e77b06d2Stomee 	jobject low64;
983*e77b06d2Stomee 	jobject tmp;
984*e77b06d2Stomee 
985*e77b06d2Stomee 	val128 = (*jenv)->CallStaticObjectMethod(jenv, g_bigint_jc,
986*e77b06d2Stomee 	    g_bigint_val_jsm, high);
987*e77b06d2Stomee 	tmp = val128;
988*e77b06d2Stomee 	val128 = (*jenv)->CallObjectMethod(jenv, tmp, g_bigint_shl_jm, 64);
989*e77b06d2Stomee 	(*jenv)->DeleteLocalRef(jenv, tmp);
990*e77b06d2Stomee 	low64 = dtj_uint64(jenv, low);
991*e77b06d2Stomee 	tmp = val128;
992*e77b06d2Stomee 	val128 = (*jenv)->CallObjectMethod(jenv, tmp, g_bigint_or_jm, low64);
993*e77b06d2Stomee 	(*jenv)->DeleteLocalRef(jenv, tmp);
994*e77b06d2Stomee 	(*jenv)->DeleteLocalRef(jenv, low64);
995*e77b06d2Stomee 
996*e77b06d2Stomee 	return (val128);
997*e77b06d2Stomee }
998*e77b06d2Stomee 
999fb3fb4f3Stomee jstring
dtj_format_string(JNIEnv * jenv,const char * fmt,...)1000fb3fb4f3Stomee dtj_format_string(JNIEnv *jenv, const char *fmt, ...)
1001fb3fb4f3Stomee {
1002fb3fb4f3Stomee 	va_list ap;
1003fb3fb4f3Stomee 	char str[DTJ_MSG_SIZE];
1004fb3fb4f3Stomee 
1005fb3fb4f3Stomee 	jstring jstr = NULL;
1006fb3fb4f3Stomee 
1007fb3fb4f3Stomee 	va_start(ap, fmt);
1008fb3fb4f3Stomee 	(void) vsnprintf(str, sizeof (str), fmt, ap);
1009fb3fb4f3Stomee 	va_end(ap);
1010fb3fb4f3Stomee 
1011fb3fb4f3Stomee 	jstr = dtj_NewStringNative(jenv, str);
1012fb3fb4f3Stomee 	/* return NULL if OutOfMemoryError pending */
1013fb3fb4f3Stomee 	return (jstr);
1014fb3fb4f3Stomee }
1015fb3fb4f3Stomee 
1016fb3fb4f3Stomee jstring
dtj_NewStringNative(JNIEnv * jenv,const char * str)1017fb3fb4f3Stomee dtj_NewStringNative(JNIEnv *jenv, const char *str)
1018fb3fb4f3Stomee {
1019fb3fb4f3Stomee 	jstring result;
1020fb3fb4f3Stomee 	jbyteArray bytes = 0;
1021fb3fb4f3Stomee 	int len;
1022fb3fb4f3Stomee 
1023fb3fb4f3Stomee 	if (!g_dtj_load_common) {
1024fb3fb4f3Stomee 		dtj_throw_illegal_state(jenv,
1025fb3fb4f3Stomee 		    "dtj_load_common() has not been called");
1026fb3fb4f3Stomee 		return (NULL);
1027fb3fb4f3Stomee 	}
1028fb3fb4f3Stomee 
1029fb3fb4f3Stomee 	len = strlen(str);
1030fb3fb4f3Stomee 
1031fb3fb4f3Stomee 	bytes = (*jenv)->NewByteArray(jenv, len);
1032fb3fb4f3Stomee 	if (!bytes) {
1033fb3fb4f3Stomee 		return (NULL); /* OutOfMemoryError pending */
1034fb3fb4f3Stomee 	}
1035fb3fb4f3Stomee 	(*jenv)->SetByteArrayRegion(jenv, bytes, 0, len,
1036fb3fb4f3Stomee 	    (jbyte *)str);
1037fb3fb4f3Stomee 	if ((*jenv)->ExceptionCheck(jenv)) {
1038fb3fb4f3Stomee 		(*jenv)->DeleteLocalRef(jenv, bytes);
1039fb3fb4f3Stomee 		return (NULL); /* ArrayIndexOutOfBoundsException pending */
1040fb3fb4f3Stomee 	}
1041fb3fb4f3Stomee 	result = (*jenv)->NewObject(jenv, g_string_jc, g_strinit_bytes_jm,
1042fb3fb4f3Stomee 	    bytes);
1043fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, bytes);
1044fb3fb4f3Stomee 	/* return NULL result if exception pending */
1045fb3fb4f3Stomee 	return (result);
1046fb3fb4f3Stomee }
1047fb3fb4f3Stomee 
1048fb3fb4f3Stomee char *
dtj_GetStringNativeChars(JNIEnv * jenv,jstring jstr)1049fb3fb4f3Stomee dtj_GetStringNativeChars(JNIEnv *jenv, jstring jstr)
1050fb3fb4f3Stomee {
1051fb3fb4f3Stomee 	jbyteArray bytes = NULL;
1052fb3fb4f3Stomee 
1053fb3fb4f3Stomee 	jint len;
1054fb3fb4f3Stomee 	char *result = NULL;
1055fb3fb4f3Stomee 
1056fb3fb4f3Stomee 	if (!g_dtj_load_common) {
1057fb3fb4f3Stomee 		dtj_throw_illegal_state(jenv,
1058fb3fb4f3Stomee 		    "dtj_load_common() has not been called");
1059fb3fb4f3Stomee 		return (NULL);
1060fb3fb4f3Stomee 	}
1061fb3fb4f3Stomee 
1062fb3fb4f3Stomee 	bytes = (*jenv)->CallObjectMethod(jenv, jstr, g_strbytes_jm);
1063fb3fb4f3Stomee 	if ((*jenv)->ExceptionCheck(jenv)) {
1064fb3fb4f3Stomee 		return (NULL); /* OutOfMemoryError pending */
1065fb3fb4f3Stomee 	}
1066fb3fb4f3Stomee 	/* Does not throw exceptions */
1067fb3fb4f3Stomee 	len = (*jenv)->GetArrayLength(jenv, bytes);
1068fb3fb4f3Stomee 	result = malloc(len + 1);
1069fb3fb4f3Stomee 	if (!result) {
1070fb3fb4f3Stomee 		(*jenv)->DeleteLocalRef(jenv, bytes);
1071fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv,
1072fb3fb4f3Stomee 		    "could not allocate native chars");
1073fb3fb4f3Stomee 		return (NULL);
1074fb3fb4f3Stomee 	}
1075fb3fb4f3Stomee 
1076fb3fb4f3Stomee 	/* Skip check for ArrayIndexOutOfBoundsException */
1077fb3fb4f3Stomee 	(*jenv)->GetByteArrayRegion(jenv, bytes, 0, len,
1078fb3fb4f3Stomee 	    (jbyte *)result);
1079fb3fb4f3Stomee 	(*jenv)->DeleteLocalRef(jenv, bytes);
1080fb3fb4f3Stomee 	result[len] = '\0'; /* NUL-terminate */
1081fb3fb4f3Stomee 
1082fb3fb4f3Stomee 	return (result);
1083fb3fb4f3Stomee }
1084fb3fb4f3Stomee 
1085fb3fb4f3Stomee void
1086fb3fb4f3Stomee /* ARGSUSED */
dtj_ReleaseStringNativeChars(JNIEnv * jenv,jstring jstr,const char * str)1087fb3fb4f3Stomee dtj_ReleaseStringNativeChars(JNIEnv *jenv, jstring jstr, const char *str)
1088fb3fb4f3Stomee {
1089fb3fb4f3Stomee 	free((void *)str);
1090fb3fb4f3Stomee }
1091fb3fb4f3Stomee 
1092fb3fb4f3Stomee char **
dtj_get_argv(JNIEnv * jenv,jobjectArray args,int * argc)1093fb3fb4f3Stomee dtj_get_argv(JNIEnv *jenv, jobjectArray args, int *argc)
1094fb3fb4f3Stomee {
1095fb3fb4f3Stomee 	char **argv = NULL; /* return value */
1096fb3fb4f3Stomee 	const char *str;
1097fb3fb4f3Stomee 	int i;
1098fb3fb4f3Stomee 
1099fb3fb4f3Stomee 	jstring jstr = NULL;
1100fb3fb4f3Stomee 
1101fb3fb4f3Stomee 	if (!g_dtj_load_common) {
1102fb3fb4f3Stomee 		dtj_throw_illegal_state(jenv,
1103fb3fb4f3Stomee 		    "dtj_load_common() has not been called");
1104fb3fb4f3Stomee 		return (NULL);
1105fb3fb4f3Stomee 	}
1106fb3fb4f3Stomee 
1107fb3fb4f3Stomee 	*argc = (*jenv)->GetArrayLength(jenv, args);
1108fb3fb4f3Stomee 	/*
1109fb3fb4f3Stomee 	 * Initialize all string pointers to NULL so that in case of an error
1110fb3fb4f3Stomee 	 * filling in the array, free_argv() will not attempt to free the
1111fb3fb4f3Stomee 	 * unallocated elements.  Also NULL-terminate the string array for
1112fb3fb4f3Stomee 	 * functions that expect terminating NULL rather than rely on argc.
1113fb3fb4f3Stomee 	 */
1114fb3fb4f3Stomee 	argv = uu_zalloc((sizeof (char *)) * (*argc + 1));
1115fb3fb4f3Stomee 	if (!argv) {
1116fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv, "Failed to allocate args array");
1117fb3fb4f3Stomee 		return (NULL);
1118fb3fb4f3Stomee 	}
1119fb3fb4f3Stomee 
1120fb3fb4f3Stomee 	for (i = 0; i < *argc; ++i) {
1121fb3fb4f3Stomee 		jstr = (*jenv)->GetObjectArrayElement(jenv, args, i);
1122fb3fb4f3Stomee 		if ((*jenv)->ExceptionCheck(jenv)) {
1123fb3fb4f3Stomee 			dtj_free_argv(argv);
1124fb3fb4f3Stomee 			return (NULL);
1125fb3fb4f3Stomee 		}
1126fb3fb4f3Stomee 		str = dtj_GetStringNativeChars(jenv, jstr);
1127fb3fb4f3Stomee 		if ((*jenv)->ExceptionCheck(jenv)) {
1128fb3fb4f3Stomee 			dtj_free_argv(argv);
1129fb3fb4f3Stomee 			(*jenv)->DeleteLocalRef(jenv, jstr);
1130fb3fb4f3Stomee 			return (NULL);
1131fb3fb4f3Stomee 		}
1132fb3fb4f3Stomee 		argv[i] = malloc(strlen(str) + 1);
1133fb3fb4f3Stomee 		if (!argv[i]) {
1134fb3fb4f3Stomee 			dtj_throw_out_of_memory(jenv, "Failed to allocate arg");
1135fb3fb4f3Stomee 			dtj_free_argv(argv);
1136fb3fb4f3Stomee 			dtj_ReleaseStringNativeChars(jenv, jstr, str);
1137fb3fb4f3Stomee 			(*jenv)->DeleteLocalRef(jenv, jstr);
1138fb3fb4f3Stomee 			return (NULL);
1139fb3fb4f3Stomee 		}
1140fb3fb4f3Stomee 		(void) strcpy(argv[i], str);
1141fb3fb4f3Stomee 		dtj_ReleaseStringNativeChars(jenv, jstr, str);
1142fb3fb4f3Stomee 		(*jenv)->DeleteLocalRef(jenv, jstr);
1143fb3fb4f3Stomee 		jstr = NULL;
1144fb3fb4f3Stomee 	}
1145fb3fb4f3Stomee 
1146fb3fb4f3Stomee 	return (argv);
1147fb3fb4f3Stomee }
1148fb3fb4f3Stomee 
1149fb3fb4f3Stomee char **
dtj_make_argv(JNIEnv * jenv,jstring command,int * argc)1150fb3fb4f3Stomee dtj_make_argv(JNIEnv *jenv, jstring command, int *argc)
1151fb3fb4f3Stomee {
1152fb3fb4f3Stomee 	const char *ws = "\f\n\r\t\v ";
1153fb3fb4f3Stomee 	char **argv = NULL; /* return value */
1154fb3fb4f3Stomee 	const char *cmd; /* native command string */
1155fb3fb4f3Stomee 	char *s; /* writable command */
1156fb3fb4f3Stomee 	char *tok; /* token */
1157fb3fb4f3Stomee 	int len;
1158fb3fb4f3Stomee 
1159fb3fb4f3Stomee 	if (!g_dtj_load_common) {
1160fb3fb4f3Stomee 		dtj_throw_illegal_state(jenv,
1161fb3fb4f3Stomee 		    "dtj_load_common() has not been called");
1162fb3fb4f3Stomee 		return (NULL);
1163fb3fb4f3Stomee 	}
1164fb3fb4f3Stomee 
1165fb3fb4f3Stomee 	if (!command) {
1166fb3fb4f3Stomee 		dtj_throw_null_pointer(jenv, "command is null");
1167fb3fb4f3Stomee 		return (NULL);
1168fb3fb4f3Stomee 	} else if ((*jenv)->GetStringLength(jenv, command) == 0) {
1169fb3fb4f3Stomee 		dtj_throw_illegal_argument(jenv, "command is empty");
1170fb3fb4f3Stomee 		return (NULL);
1171fb3fb4f3Stomee 	}
1172fb3fb4f3Stomee 
1173fb3fb4f3Stomee 	cmd = dtj_GetStringNativeChars(jenv, command);
1174fb3fb4f3Stomee 	if ((*jenv)->ExceptionCheck(jenv)) {
1175fb3fb4f3Stomee 		return (NULL);
1176fb3fb4f3Stomee 	}
1177fb3fb4f3Stomee 	len = strlen(cmd);
1178fb3fb4f3Stomee 	s = malloc(len + 1);
1179fb3fb4f3Stomee 	if (!s) {
1180fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv,
1181fb3fb4f3Stomee 		    "failed to allocate command string");
1182fb3fb4f3Stomee 		dtj_ReleaseStringNativeChars(jenv, command, cmd);
1183fb3fb4f3Stomee 		return (NULL);
1184fb3fb4f3Stomee 	}
1185fb3fb4f3Stomee 	(void) strcpy(s, cmd);
1186fb3fb4f3Stomee 	/*
1187fb3fb4f3Stomee 	 * Initialize all string pointers to NULL so that in case of an error
1188fb3fb4f3Stomee 	 * filling in the array, free_argv() will not attempt to free the
1189fb3fb4f3Stomee 	 * unallocated elements.  Also NULL-terminate the string array for
1190fb3fb4f3Stomee 	 * functions that expect terminating NULL rather than rely on argc.
1191fb3fb4f3Stomee 	 * Allow for maximum length resulting from single-character tokens
1192fb3fb4f3Stomee 	 * separated by single spaces.
1193fb3fb4f3Stomee 	 */
1194fb3fb4f3Stomee 	argv = uu_zalloc(sizeof (char *) * (len / 2 + 1));
1195fb3fb4f3Stomee 	if (!argv) {
1196fb3fb4f3Stomee 		dtj_throw_out_of_memory(jenv, "failed to allocate args array");
1197fb3fb4f3Stomee 		free(s);
1198fb3fb4f3Stomee 		dtj_ReleaseStringNativeChars(jenv, command, cmd);
1199fb3fb4f3Stomee 		return (NULL);
1200fb3fb4f3Stomee 	}
1201fb3fb4f3Stomee 
1202fb3fb4f3Stomee 	*argc = 0;
1203fb3fb4f3Stomee 	for (tok = strtok(s, ws); tok != NULL; tok = strtok(NULL, ws)) {
1204fb3fb4f3Stomee 		argv[*argc] = malloc(strlen(tok) + 1);
1205fb3fb4f3Stomee 		if (!argv[*argc]) {
1206fb3fb4f3Stomee 			dtj_throw_out_of_memory(jenv, "Failed to allocate arg");
1207fb3fb4f3Stomee 			dtj_free_argv(argv);
1208fb3fb4f3Stomee 			free(s);
1209fb3fb4f3Stomee 			dtj_ReleaseStringNativeChars(jenv, command, cmd);
1210fb3fb4f3Stomee 			return (NULL);
1211fb3fb4f3Stomee 		}
1212fb3fb4f3Stomee 		(void) strcpy(argv[(*argc)++], tok);
1213fb3fb4f3Stomee 	}
1214fb3fb4f3Stomee 
1215fb3fb4f3Stomee 	if (*argc == 0) {
1216fb3fb4f3Stomee 		dtj_throw_illegal_argument(jenv, "command is blank");
1217fb3fb4f3Stomee 		dtj_free_argv(argv);
1218fb3fb4f3Stomee 		free(s);
1219fb3fb4f3Stomee 		dtj_ReleaseStringNativeChars(jenv, command, cmd);
1220fb3fb4f3Stomee 		return (NULL);
1221fb3fb4f3Stomee 	}
1222fb3fb4f3Stomee 
1223fb3fb4f3Stomee 	free(s);
1224fb3fb4f3Stomee 	dtj_ReleaseStringNativeChars(jenv, command, cmd);
1225fb3fb4f3Stomee 	return (argv);
1226fb3fb4f3Stomee }
1227fb3fb4f3Stomee 
1228fb3fb4f3Stomee void
dtj_free_argv(char ** argv)1229fb3fb4f3Stomee dtj_free_argv(char **argv)
1230fb3fb4f3Stomee {
1231fb3fb4f3Stomee 	if (argv) {
1232fb3fb4f3Stomee 		char **s = argv;
1233fb3fb4f3Stomee 		while (*s) {
1234fb3fb4f3Stomee 			free((void *)*s);
1235fb3fb4f3Stomee 			*s++ = NULL;
1236fb3fb4f3Stomee 		}
1237fb3fb4f3Stomee 		free((void *)argv);
1238fb3fb4f3Stomee 	}
1239fb3fb4f3Stomee }
1240fb3fb4f3Stomee 
1241fb3fb4f3Stomee 
1242fb3fb4f3Stomee /* Wrappers for uu_list_t */
1243fb3fb4f3Stomee 
1244fb3fb4f3Stomee int
1245fb3fb4f3Stomee /* ARGSUSED */
dtj_pointer_list_entry_cmp(const void * v1,const void * v2,void * arg)1246fb3fb4f3Stomee dtj_pointer_list_entry_cmp(const void *v1, const void *v2, void *arg)
1247fb3fb4f3Stomee {
1248fb3fb4f3Stomee 	const dtj_pointer_list_entry_t *p1 = v1;
1249fb3fb4f3Stomee 	const dtj_pointer_list_entry_t *p2 = v2;
1250fb3fb4f3Stomee 
1251fb3fb4f3Stomee 	/*
1252fb3fb4f3Stomee 	 * It is not valid to compare pointers using the relational operators
1253fb3fb4f3Stomee 	 * unless they point to elements in the same array.
1254fb3fb4f3Stomee 	 */
125580ab886dSwesolows 	uint64_t x = (uintptr_t)p1->dple_ptr;
125680ab886dSwesolows 	uint64_t y = (uintptr_t)p2->dple_ptr;
1257fb3fb4f3Stomee 	int rc;
1258fb3fb4f3Stomee 	rc = ((x > y) ? 1 : ((x < y) ? -1 : 0));
1259fb3fb4f3Stomee 	return (rc);
1260fb3fb4f3Stomee }
1261fb3fb4f3Stomee 
1262fb3fb4f3Stomee int
1263fb3fb4f3Stomee /* ARGSUSED */
dtj_string_list_entry_cmp(const void * v1,const void * v2,void * arg)1264fb3fb4f3Stomee dtj_string_list_entry_cmp(const void *v1, const void *v2, void *arg)
1265fb3fb4f3Stomee {
1266fb3fb4f3Stomee 	const dtj_string_list_entry_t *p1 = v1;
1267fb3fb4f3Stomee 	const dtj_string_list_entry_t *p2 = v2;
1268fb3fb4f3Stomee 	const char *s1 = p1->dsle_value;
1269fb3fb4f3Stomee 	const char *s2 = p2->dsle_value;
1270fb3fb4f3Stomee 	if (s1 == NULL) {
1271fb3fb4f3Stomee 		return (s2 == NULL ? 0 : -1);
1272fb3fb4f3Stomee 	}
1273fb3fb4f3Stomee 	if (s2 == NULL) {
1274fb3fb4f3Stomee 		return (1);
1275fb3fb4f3Stomee 	}
1276fb3fb4f3Stomee 	return (strcmp(s1, s2));
1277fb3fb4f3Stomee }
1278fb3fb4f3Stomee 
1279fb3fb4f3Stomee static boolean_t
dtj_check_pointer_pool(void)1280fb3fb4f3Stomee dtj_check_pointer_pool(void)
1281fb3fb4f3Stomee {
1282fb3fb4f3Stomee 	if (g_pointer_pool == NULL) {
1283fb3fb4f3Stomee 		g_pointer_pool = uu_list_pool_create("g_pointer_pool",
1284fb3fb4f3Stomee 		    sizeof (dtj_pointer_list_entry_t),
1285fb3fb4f3Stomee 		    offsetof(dtj_pointer_list_entry_t, dple_node),
1286fb3fb4f3Stomee 		    dtj_pointer_list_entry_cmp,
1287fb3fb4f3Stomee 		    (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
1288fb3fb4f3Stomee 		if (g_pointer_pool == NULL) {
1289fb3fb4f3Stomee 			return (B_FALSE);
1290fb3fb4f3Stomee 		}
1291fb3fb4f3Stomee 	}
1292fb3fb4f3Stomee 	return (B_TRUE);
1293fb3fb4f3Stomee }
1294fb3fb4f3Stomee 
1295fb3fb4f3Stomee uu_list_t *
dtj_pointer_list_create(void)1296fb3fb4f3Stomee dtj_pointer_list_create(void)
1297fb3fb4f3Stomee {
1298fb3fb4f3Stomee 	uu_list_t *list;
1299fb3fb4f3Stomee 
1300fb3fb4f3Stomee 	if (!dtj_check_pointer_pool()) {
1301fb3fb4f3Stomee 		return (NULL);
1302fb3fb4f3Stomee 	}
1303fb3fb4f3Stomee 
1304fb3fb4f3Stomee 	list = uu_list_create(g_pointer_pool, NULL,
1305fb3fb4f3Stomee 	    (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
1306fb3fb4f3Stomee 	return (list);
1307fb3fb4f3Stomee }
1308fb3fb4f3Stomee 
1309fb3fb4f3Stomee dtj_pointer_list_entry_t *
dtj_pointer_list_entry_create(void * p)1310fb3fb4f3Stomee dtj_pointer_list_entry_create(void *p)
1311fb3fb4f3Stomee {
1312fb3fb4f3Stomee 	dtj_pointer_list_entry_t *e;
1313fb3fb4f3Stomee 
1314fb3fb4f3Stomee 	if (!dtj_check_pointer_pool()) {
1315fb3fb4f3Stomee 		return (NULL);
1316fb3fb4f3Stomee 	}
1317fb3fb4f3Stomee 
1318fb3fb4f3Stomee 	e = uu_zalloc(sizeof (dtj_pointer_list_entry_t));
1319fb3fb4f3Stomee 	if (e) {
1320fb3fb4f3Stomee 		uu_list_node_init(e, &e->dple_node, g_pointer_pool);
1321fb3fb4f3Stomee 		e->dple_ptr = p;
1322fb3fb4f3Stomee 	}
1323fb3fb4f3Stomee 	return (e);
1324fb3fb4f3Stomee }
1325fb3fb4f3Stomee 
1326fb3fb4f3Stomee static boolean_t
dtj_check_string_pool(void)1327fb3fb4f3Stomee dtj_check_string_pool(void)
1328fb3fb4f3Stomee {
1329fb3fb4f3Stomee 	if (g_string_pool == NULL) {
1330fb3fb4f3Stomee 		g_string_pool = uu_list_pool_create("g_string_pool",
1331fb3fb4f3Stomee 		    sizeof (dtj_string_list_entry_t),
1332fb3fb4f3Stomee 		    offsetof(dtj_string_list_entry_t, dsle_node),
1333fb3fb4f3Stomee 		    dtj_string_list_entry_cmp,
1334fb3fb4f3Stomee 		    (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
1335fb3fb4f3Stomee 		if (g_string_pool == NULL) {
1336fb3fb4f3Stomee 			return (B_FALSE);
1337fb3fb4f3Stomee 		}
1338fb3fb4f3Stomee 	}
1339fb3fb4f3Stomee 	return (B_TRUE);
1340fb3fb4f3Stomee }
1341fb3fb4f3Stomee 
1342fb3fb4f3Stomee uu_list_t *
dtj_string_list_create(void)1343fb3fb4f3Stomee dtj_string_list_create(void)
1344fb3fb4f3Stomee {
1345fb3fb4f3Stomee 	uu_list_t *list;
1346fb3fb4f3Stomee 
1347fb3fb4f3Stomee 	if (!dtj_check_string_pool()) {
1348fb3fb4f3Stomee 		return (NULL);
1349fb3fb4f3Stomee 	}
1350fb3fb4f3Stomee 
1351fb3fb4f3Stomee 	list = uu_list_create(g_string_pool, NULL,
1352fb3fb4f3Stomee 	    (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
1353fb3fb4f3Stomee 	return (list);
1354fb3fb4f3Stomee }
1355fb3fb4f3Stomee 
1356fb3fb4f3Stomee dtj_string_list_entry_t *
dtj_string_list_entry_create(const char * s)1357fb3fb4f3Stomee dtj_string_list_entry_create(const char *s)
1358fb3fb4f3Stomee {
1359fb3fb4f3Stomee 	dtj_string_list_entry_t *e;
1360fb3fb4f3Stomee 
1361fb3fb4f3Stomee 	if (!dtj_check_string_pool()) {
1362fb3fb4f3Stomee 		return (NULL);
1363fb3fb4f3Stomee 	}
1364fb3fb4f3Stomee 
1365fb3fb4f3Stomee 	e = uu_zalloc(sizeof (dtj_string_list_entry_t));
1366fb3fb4f3Stomee 	if (e) {
1367fb3fb4f3Stomee 		uu_list_node_init(e, &e->dsle_node, g_string_pool);
1368fb3fb4f3Stomee 		if (s) {
1369fb3fb4f3Stomee 			e->dsle_value = malloc(strlen(s) + 1);
1370fb3fb4f3Stomee 			if (e->dsle_value) {
1371fb3fb4f3Stomee 				(void) strcpy(e->dsle_value, s);
1372fb3fb4f3Stomee 			} else {
1373fb3fb4f3Stomee 				uu_list_node_fini(e, &e->dsle_node,
1374fb3fb4f3Stomee 				    g_string_pool);
1375fb3fb4f3Stomee 				uu_free(e);
1376fb3fb4f3Stomee 				e = NULL;
1377fb3fb4f3Stomee 			}
1378fb3fb4f3Stomee 		}
1379fb3fb4f3Stomee 	}
1380fb3fb4f3Stomee 	return (e);
1381fb3fb4f3Stomee }
1382fb3fb4f3Stomee 
1383fb3fb4f3Stomee void
dtj_pointer_list_entry_destroy(void * v,dtj_value_destroy_f * value_destroy,void * arg)1384fb3fb4f3Stomee dtj_pointer_list_entry_destroy(void *v,
1385fb3fb4f3Stomee     dtj_value_destroy_f *value_destroy, void *arg)
1386fb3fb4f3Stomee {
1387fb3fb4f3Stomee 	if (v) {
1388fb3fb4f3Stomee 		dtj_pointer_list_entry_t *e = v;
1389fb3fb4f3Stomee 		if (value_destroy) {
1390fb3fb4f3Stomee 			value_destroy(e->dple_ptr, arg);
1391fb3fb4f3Stomee 		}
1392fb3fb4f3Stomee 		uu_list_node_fini(e, &e->dple_node, g_pointer_pool);
1393fb3fb4f3Stomee 		e->dple_ptr = NULL;
1394fb3fb4f3Stomee 		uu_free(v);
1395fb3fb4f3Stomee 	}
1396fb3fb4f3Stomee }
1397fb3fb4f3Stomee 
1398fb3fb4f3Stomee void
1399fb3fb4f3Stomee /* ARGSUSED */
dtj_string_list_entry_destroy(void * v,void * arg)1400fb3fb4f3Stomee dtj_string_list_entry_destroy(void *v, void *arg)
1401fb3fb4f3Stomee {
1402fb3fb4f3Stomee 	if (v) {
1403fb3fb4f3Stomee 		dtj_string_list_entry_t *e = v;
1404fb3fb4f3Stomee 		free(e->dsle_value);
1405fb3fb4f3Stomee 		uu_list_node_fini(e, &e->dsle_node, g_string_pool);
1406fb3fb4f3Stomee 		e->dsle_value = NULL;
1407fb3fb4f3Stomee 		uu_free(v);
1408fb3fb4f3Stomee 	}
1409fb3fb4f3Stomee }
1410fb3fb4f3Stomee 
1411fb3fb4f3Stomee void
dtj_list_clear(uu_list_t * list,dtj_value_destroy_f * value_destroy,void * arg)1412fb3fb4f3Stomee dtj_list_clear(uu_list_t *list, dtj_value_destroy_f *value_destroy,
1413fb3fb4f3Stomee     void *arg)
1414fb3fb4f3Stomee {
1415fb3fb4f3Stomee 	void *cookie; /* needed for uu_list_teardown */
1416fb3fb4f3Stomee 	void *value;
1417fb3fb4f3Stomee 
1418fb3fb4f3Stomee 	if (!list) {
1419fb3fb4f3Stomee 		return;
1420fb3fb4f3Stomee 	}
1421fb3fb4f3Stomee 
1422fb3fb4f3Stomee 	cookie = NULL;
1423fb3fb4f3Stomee 	if (value_destroy) {
1424fb3fb4f3Stomee 		while ((value = uu_list_teardown(list, &cookie)) != NULL) {
1425fb3fb4f3Stomee 			value_destroy(value, arg);
1426fb3fb4f3Stomee 		}
1427fb3fb4f3Stomee 	} else {
1428fb3fb4f3Stomee 		while ((value = uu_list_teardown(list, &cookie)) != NULL) {
1429fb3fb4f3Stomee 		}
1430fb3fb4f3Stomee 	}
1431fb3fb4f3Stomee }
1432fb3fb4f3Stomee 
1433fb3fb4f3Stomee void
dtj_list_destroy(uu_list_t * list,dtj_value_destroy_f * value_destroy,void * arg)1434fb3fb4f3Stomee dtj_list_destroy(uu_list_t *list,
1435fb3fb4f3Stomee     dtj_value_destroy_f *value_destroy, void *arg)
1436fb3fb4f3Stomee {
1437fb3fb4f3Stomee 	dtj_list_clear(list, value_destroy, arg);
1438fb3fb4f3Stomee 	uu_list_destroy(list);
1439fb3fb4f3Stomee }
1440fb3fb4f3Stomee 
1441fb3fb4f3Stomee void
dtj_pointer_list_clear(uu_list_t * list,dtj_value_destroy_f * value_destroy,void * arg)1442fb3fb4f3Stomee dtj_pointer_list_clear(uu_list_t *list,
1443fb3fb4f3Stomee     dtj_value_destroy_f *value_destroy, void *arg)
1444fb3fb4f3Stomee {
1445fb3fb4f3Stomee 	void *cookie; /* needed for uu_list_teardown */
1446fb3fb4f3Stomee 	dtj_pointer_list_entry_t *e;
1447fb3fb4f3Stomee 
1448fb3fb4f3Stomee 	if (!list) {
1449fb3fb4f3Stomee 		return;
1450fb3fb4f3Stomee 	}
1451fb3fb4f3Stomee 
1452fb3fb4f3Stomee 	cookie = NULL;
1453fb3fb4f3Stomee 	while ((e = uu_list_teardown(list, &cookie)) != NULL) {
1454fb3fb4f3Stomee 		dtj_pointer_list_entry_destroy(e, value_destroy, arg);
1455fb3fb4f3Stomee 	}
1456fb3fb4f3Stomee }
1457fb3fb4f3Stomee 
1458fb3fb4f3Stomee void
dtj_pointer_list_destroy(uu_list_t * list,dtj_value_destroy_f * value_destroy,void * arg)1459fb3fb4f3Stomee dtj_pointer_list_destroy(uu_list_t *list,
1460fb3fb4f3Stomee     dtj_value_destroy_f *value_destroy, void *arg)
1461fb3fb4f3Stomee {
1462fb3fb4f3Stomee 	dtj_pointer_list_clear(list, value_destroy, arg);
1463fb3fb4f3Stomee 	uu_list_destroy(list);
1464fb3fb4f3Stomee }
1465fb3fb4f3Stomee 
1466fb3fb4f3Stomee void
dtj_string_list_clear(uu_list_t * list)1467fb3fb4f3Stomee dtj_string_list_clear(uu_list_t *list)
1468fb3fb4f3Stomee {
1469fb3fb4f3Stomee 	dtj_list_clear(list, dtj_string_list_entry_destroy, NULL);
1470fb3fb4f3Stomee }
1471fb3fb4f3Stomee 
1472fb3fb4f3Stomee void
dtj_string_list_destroy(uu_list_t * list)1473fb3fb4f3Stomee dtj_string_list_destroy(uu_list_t *list)
1474fb3fb4f3Stomee {
1475fb3fb4f3Stomee 	dtj_list_destroy(list, dtj_string_list_entry_destroy, NULL);
1476fb3fb4f3Stomee }
1477fb3fb4f3Stomee 
1478fb3fb4f3Stomee boolean_t
dtj_list_empty(uu_list_t * list)1479fb3fb4f3Stomee dtj_list_empty(uu_list_t *list)
1480fb3fb4f3Stomee {
1481fb3fb4f3Stomee 	return (uu_list_numnodes(list) == 0);
1482fb3fb4f3Stomee }
1483fb3fb4f3Stomee 
1484fb3fb4f3Stomee boolean_t
dtj_list_add(uu_list_t * list,void * value)1485fb3fb4f3Stomee dtj_list_add(uu_list_t *list, void *value)
1486fb3fb4f3Stomee {
1487fb3fb4f3Stomee 	return (uu_list_insert_before(list, NULL, value) == 0);
1488fb3fb4f3Stomee }
1489fb3fb4f3Stomee 
1490fb3fb4f3Stomee boolean_t
dtj_pointer_list_add(uu_list_t * list,void * p)1491fb3fb4f3Stomee dtj_pointer_list_add(uu_list_t *list, void *p)
1492fb3fb4f3Stomee {
1493fb3fb4f3Stomee 	dtj_pointer_list_entry_t *e = dtj_pointer_list_entry_create(p);
1494fb3fb4f3Stomee 	if (!e) {
1495fb3fb4f3Stomee 		return (B_FALSE);
1496fb3fb4f3Stomee 	}
1497fb3fb4f3Stomee 	return (dtj_list_add(list, e));
1498fb3fb4f3Stomee }
1499fb3fb4f3Stomee 
1500fb3fb4f3Stomee void *
dtj_pointer_list_walk_next(uu_list_walk_t * itr)1501fb3fb4f3Stomee dtj_pointer_list_walk_next(uu_list_walk_t *itr)
1502fb3fb4f3Stomee {
1503fb3fb4f3Stomee 	dtj_pointer_list_entry_t *e = uu_list_walk_next(itr);
1504fb3fb4f3Stomee 	if (!e) {
1505fb3fb4f3Stomee 		return (DTJ_INVALID_PTR);
1506fb3fb4f3Stomee 	}
1507fb3fb4f3Stomee 	return (e->dple_ptr);
1508fb3fb4f3Stomee }
1509fb3fb4f3Stomee 
1510fb3fb4f3Stomee void *
dtj_pointer_list_first(uu_list_t * list)1511fb3fb4f3Stomee dtj_pointer_list_first(uu_list_t *list)
1512fb3fb4f3Stomee {
1513fb3fb4f3Stomee 	dtj_pointer_list_entry_t *e = uu_list_first(list);
1514fb3fb4f3Stomee 	if (!e) {
1515fb3fb4f3Stomee 		/* NULL is a valid value; use -1 for invalid */
1516fb3fb4f3Stomee 		return (DTJ_INVALID_PTR);
1517fb3fb4f3Stomee 	}
1518fb3fb4f3Stomee 	return (e->dple_ptr);
1519fb3fb4f3Stomee }
1520fb3fb4f3Stomee 
1521fb3fb4f3Stomee void *
dtj_pointer_list_last(uu_list_t * list)1522fb3fb4f3Stomee dtj_pointer_list_last(uu_list_t *list)
1523fb3fb4f3Stomee {
1524fb3fb4f3Stomee 	dtj_pointer_list_entry_t *e = uu_list_last(list);
1525fb3fb4f3Stomee 	if (!e) {
1526fb3fb4f3Stomee 		/* NULL is a valid value; use -1 for invalid */
1527fb3fb4f3Stomee 		return (DTJ_INVALID_PTR);
1528fb3fb4f3Stomee 	}
1529fb3fb4f3Stomee 	return (e->dple_ptr);
1530fb3fb4f3Stomee }
1531fb3fb4f3Stomee 
1532fb3fb4f3Stomee boolean_t
dtj_string_list_add(uu_list_t * list,const char * s)1533fb3fb4f3Stomee dtj_string_list_add(uu_list_t *list, const char *s)
1534fb3fb4f3Stomee {
1535fb3fb4f3Stomee 	dtj_string_list_entry_t *e = dtj_string_list_entry_create(s);
1536fb3fb4f3Stomee 	if (!e) {
1537fb3fb4f3Stomee 		return (B_FALSE);
1538fb3fb4f3Stomee 	}
1539fb3fb4f3Stomee 	return (dtj_list_add(list, e));
1540fb3fb4f3Stomee }
1541fb3fb4f3Stomee 
1542fb3fb4f3Stomee const char *
dtj_string_list_walk_next(uu_list_walk_t * itr)1543fb3fb4f3Stomee dtj_string_list_walk_next(uu_list_walk_t *itr)
1544fb3fb4f3Stomee {
1545fb3fb4f3Stomee 	dtj_string_list_entry_t *e = uu_list_walk_next(itr);
1546fb3fb4f3Stomee 	if (!e) {
1547fb3fb4f3Stomee 		return (DTJ_INVALID_STR);
1548fb3fb4f3Stomee 	}
1549fb3fb4f3Stomee 	return (e->dsle_value);
1550fb3fb4f3Stomee }
1551fb3fb4f3Stomee 
1552fb3fb4f3Stomee const char *
dtj_string_list_first(uu_list_t * list)1553fb3fb4f3Stomee dtj_string_list_first(uu_list_t *list)
1554fb3fb4f3Stomee {
1555fb3fb4f3Stomee 	dtj_string_list_entry_t *e = uu_list_first(list);
1556fb3fb4f3Stomee 	if (!e) {
1557fb3fb4f3Stomee 		/* NULL is a valid string value; use -1 for invalid */
1558fb3fb4f3Stomee 		return (DTJ_INVALID_STR);
1559fb3fb4f3Stomee 	}
1560fb3fb4f3Stomee 	return (e->dsle_value);
1561fb3fb4f3Stomee }
1562fb3fb4f3Stomee 
1563fb3fb4f3Stomee const char *
dtj_string_list_last(uu_list_t * list)1564fb3fb4f3Stomee dtj_string_list_last(uu_list_t *list)
1565fb3fb4f3Stomee {
1566fb3fb4f3Stomee 	dtj_string_list_entry_t *e = uu_list_last(list);
1567fb3fb4f3Stomee 	if (!e) {
1568fb3fb4f3Stomee 		/* NULL is a valid string value; use -1 for invalid */
1569fb3fb4f3Stomee 		return (DTJ_INVALID_STR);
1570fb3fb4f3Stomee 	}
1571fb3fb4f3Stomee 	return (e->dsle_value);
1572fb3fb4f3Stomee }
1573