11449Stomee /*
21449Stomee * CDDL HEADER START
31449Stomee *
41449Stomee * The contents of this file are subject to the terms of the
51449Stomee * Common Development and Distribution License (the "License").
61449Stomee * You may not use this file except in compliance with the License.
71449Stomee *
81449Stomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91449Stomee * or http://www.opensolaris.org/os/licensing.
101449Stomee * See the License for the specific language governing permissions
111449Stomee * and limitations under the License.
121449Stomee *
131449Stomee * When distributing Covered Code, include this CDDL HEADER in each
141449Stomee * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151449Stomee * If applicable, add the following below this CDDL HEADER, with the
161449Stomee * fields enclosed by brackets "[]" replaced with your own identifying
171449Stomee * information: Portions Copyright [yyyy] [name of copyright owner]
181449Stomee *
191449Stomee * CDDL HEADER END
201449Stomee */
211449Stomee
221449Stomee /*
23*6136Stomee * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
241449Stomee * Use is subject to license terms.
251449Stomee */
261449Stomee
271449Stomee #pragma ident "%Z%%M% %I% %E% SMI"
281449Stomee
291449Stomee #include <stdlib.h>
301449Stomee #include <stddef.h>
311449Stomee #include <sys/types.h>
321449Stomee #include <pthread.h>
331449Stomee #include <string.h>
341449Stomee #include <dtj_util.h>
351449Stomee
361449Stomee /*
371449Stomee * dtj_util.c separates functionality that is generally useful from
381449Stomee * that which is specific to the Java DTrace API. If moved to a separate
391449Stomee * library, this functionality could be shared by other JNI wrappers.
401449Stomee */
411449Stomee
421449Stomee boolean_t g_dtj_util_debug = B_FALSE;
431449Stomee static boolean_t g_dtj_load_common = B_FALSE;
441449Stomee
451449Stomee /* NativeException */
461449Stomee jclass g_nx_jc = 0;
471449Stomee jmethodID g_nxinit_jm = 0;
481449Stomee
491449Stomee /* java.io.Serializable */
501449Stomee jclass g_serial_jc = 0;
511449Stomee
521449Stomee /* java.lang.Number */
531449Stomee jclass g_number_jc = 0;
541449Stomee jmethodID g_shortval_jm = 0;
551449Stomee jmethodID g_intval_jm = 0;
561449Stomee jmethodID g_longval_jm = 0;
571449Stomee
581449Stomee /* java.lang.Byte */
591449Stomee jclass g_byte_jc = 0;
601449Stomee jmethodID g_byteinit_jm = 0;
611449Stomee
621449Stomee /* java.lang.Character */
631449Stomee jclass g_char_jc = 0;
641449Stomee jmethodID g_charinit_jm = 0;
651449Stomee jmethodID g_charval_jm = 0;
661449Stomee
671449Stomee /* java.lang.Short */
681449Stomee jclass g_short_jc = 0;
691449Stomee jmethodID g_shortinit_jm = 0;
701449Stomee
711449Stomee /* java.lang.Integer */
721449Stomee jclass g_int_jc = 0;
731449Stomee jmethodID g_intinit_jm = 0;
741449Stomee
751449Stomee /* java.lang.Long */
761449Stomee jclass g_long_jc = 0;
771449Stomee jmethodID g_longinit_jm = 0;
781449Stomee
79*6136Stomee /* java.math.BigInteger */
80*6136Stomee jclass g_bigint_jc = 0;
81*6136Stomee jmethodID g_bigint_val_jsm = 0;
82*6136Stomee jmethodID g_bigint_div_jm = 0;
83*6136Stomee jmethodID g_bigint_shl_jm = 0;
84*6136Stomee jmethodID g_bigint_or_jm = 0;
85*6136Stomee jmethodID g_bigint_setbit_jm = 0;
86*6136Stomee
871449Stomee /* java.lang.String */
881449Stomee jclass g_string_jc = 0;
891449Stomee jmethodID g_strinit_bytes_jm = 0;
901449Stomee jmethodID g_strbytes_jm = 0;
911449Stomee jmethodID g_trim_jm = 0;
921449Stomee
933645Stomee /* java.lang.StringBuilder */
941449Stomee jclass g_buf_jc = 0;
951449Stomee jmethodID g_bufinit_jm = 0;
961449Stomee jmethodID g_buf_append_char_jm = 0;
971449Stomee jmethodID g_buf_append_int_jm = 0;
981449Stomee jmethodID g_buf_append_long_jm = 0;
991449Stomee jmethodID g_buf_append_str_jm = 0;
1001449Stomee jmethodID g_buf_append_obj_jm = 0;
1011449Stomee jmethodID g_buflen_jm = 0;
1021449Stomee jmethodID g_bufsetlen_jm = 0;
1031449Stomee
1041449Stomee /* java.lang.Object */
1051449Stomee jclass g_object_jc = 0;
1061449Stomee jmethodID g_tostring_jm = 0;
1071449Stomee jmethodID g_equals_jm = 0;
1081449Stomee
1091449Stomee /* java.lang.Enum */
1101449Stomee jclass g_enum_jc = 0;
1111449Stomee jmethodID g_enumname_jm = 0;
1121449Stomee
1131449Stomee /* List */
1141449Stomee jclass g_list_jc = 0;
1151449Stomee jmethodID g_listclear_jm = 0;
1161449Stomee jmethodID g_listadd_jm = 0;
1171449Stomee jmethodID g_listget_jm = 0;
1181449Stomee jmethodID g_listsize_jm = 0;
1191449Stomee
1201449Stomee /* Global list pools */
1211449Stomee static uu_list_pool_t *g_pointer_pool = NULL;
1221449Stomee static uu_list_pool_t *g_string_pool = NULL;
1231449Stomee
1241449Stomee static dtj_status_t dtj_get_jni_classes(JNIEnv *, uu_list_t *, uu_list_pool_t *,
1251449Stomee uu_list_pool_t *, uu_list_pool_t *, const dtj_table_entry_t *);
1261449Stomee static dtj_status_t dtj_cache_jni_methods(JNIEnv *, dtj_java_class_t *);
1271449Stomee static dtj_status_t dtj_cache_jni_fields(JNIEnv *, dtj_java_class_t *);
1281449Stomee
1291449Stomee /* Constructors */
1301449Stomee static dtj_java_class_t *dtj_java_class_create(JNIEnv *, jclass *, char *,
1311449Stomee uu_list_pool_t *, uu_list_pool_t *, uu_list_pool_t *);
1321449Stomee static dtj_java_method_t *dtj_java_method_create(JNIEnv *, jmethodID *, char *,
1331449Stomee char *, uu_list_pool_t *);
1341449Stomee static dtj_java_method_t *dtj_java_static_method_create(JNIEnv *, jmethodID *,
1351449Stomee char *, char *, uu_list_pool_t *);
1361449Stomee static dtj_java_field_t *dtj_java_field_create(JNIEnv *, jfieldID *, char *,
1371449Stomee char *, uu_list_pool_t *);
1381449Stomee static dtj_java_field_t *dtj_java_static_field_create(JNIEnv *, jfieldID *,
1391449Stomee char *, char *, uu_list_pool_t *);
1401449Stomee
1411449Stomee /* Destructors */
1421449Stomee static void dtj_java_class_destroy(void *, void *);
1431449Stomee static void dtj_java_method_destroy(void *, void *);
1441449Stomee static void dtj_java_field_destroy(void *, void *);
1451449Stomee
1461449Stomee /* Comparison functions, uu_compare_fn_t signature */
1471449Stomee static int dtj_java_class_cmp(const void *, const void *, void *);
1481449Stomee static int dtj_java_method_cmp(const void *, const void *, void *);
1491449Stomee static int dtj_java_field_cmp(const void *, const void *, void *);
1501449Stomee
1511449Stomee /* Java Throwable */
1521449Stomee static void dtj_throw(JNIEnv *, jclass, const char *, va_list *);
1531449Stomee
1541449Stomee /* Support for uu_list_t wrappers */
1551449Stomee static boolean_t dtj_check_pointer_pool(void);
1561449Stomee static boolean_t dtj_check_string_pool(void);
1571449Stomee
1581449Stomee dtj_status_t
dtj_load_common(JNIEnv * jenv)1591449Stomee dtj_load_common(JNIEnv *jenv)
1601449Stomee {
1611449Stomee dtj_status_t status;
1621449Stomee
1631449Stomee static const dtj_table_entry_t table[] = {
1641449Stomee /* NativeException */
1651449Stomee { JCLASS, &g_nx_jc,
1661449Stomee "org/opensolaris/os/dtrace/NativeException" },
1671449Stomee { JMETHOD, &g_nxinit_jm, CONSTRUCTOR,
1681449Stomee "(Ljava/lang/String;ILjava/lang/Throwable;)V" },
1691449Stomee
1701449Stomee /* java.io.Serializable */
1711449Stomee { JCLASS, &g_serial_jc, "java/io/Serializable" },
1721449Stomee
1731449Stomee /* java.lang.Number */
1741449Stomee { JCLASS, &g_number_jc, "java/lang/Number" },
1751449Stomee { JMETHOD, &g_shortval_jm, "shortValue", "()S" },
1761449Stomee { JMETHOD, &g_intval_jm, "intValue", "()I" },
1771449Stomee { JMETHOD, &g_longval_jm, "longValue", "()J" },
1781449Stomee
1791449Stomee /* java.lang.Byte */
1801449Stomee { JCLASS, &g_byte_jc, "java/lang/Byte" },
1811449Stomee { JMETHOD, &g_byteinit_jm, CONSTRUCTOR, "(B)V" },
1821449Stomee
1831449Stomee /* java.lang.Character */
1841449Stomee { JCLASS, &g_char_jc, "java/lang/Character" },
1851449Stomee { JMETHOD, &g_charinit_jm, CONSTRUCTOR, "(C)V" },
1861449Stomee { JMETHOD, &g_charval_jm, "charValue", "()C" },
1871449Stomee
1881449Stomee /* java.lang.Short */
1891449Stomee { JCLASS, &g_short_jc, "java/lang/Short" },
1901449Stomee { JMETHOD, &g_shortinit_jm, CONSTRUCTOR, "(S)V" },
1911449Stomee
1921449Stomee /* java.lang.Integer */
1931449Stomee { JCLASS, &g_int_jc, "java/lang/Integer" },
1941449Stomee { JMETHOD, &g_intinit_jm, CONSTRUCTOR, "(I)V" },
1951449Stomee
1961449Stomee /* java.lang.Long */
1971449Stomee { JCLASS, &g_long_jc, "java/lang/Long" },
1981449Stomee { JMETHOD, &g_longinit_jm, CONSTRUCTOR, "(J)V" },
1991449Stomee
200*6136Stomee /* java.math.BigInteger */
201*6136Stomee { JCLASS, &g_bigint_jc, "java/math/BigInteger" },
202*6136Stomee { JMETHOD_STATIC, &g_bigint_val_jsm, "valueOf",
203*6136Stomee "(J)Ljava/math/BigInteger;" },
204*6136Stomee { JMETHOD, &g_bigint_div_jm, "divide",
205*6136Stomee "(Ljava/math/BigInteger;)Ljava/math/BigInteger;" },
206*6136Stomee { JMETHOD, &g_bigint_shl_jm, "shiftLeft",
207*6136Stomee "(I)Ljava/math/BigInteger;" },
208*6136Stomee { JMETHOD, &g_bigint_or_jm, "or",
209*6136Stomee "(Ljava/math/BigInteger;)Ljava/math/BigInteger;" },
210*6136Stomee { JMETHOD, &g_bigint_setbit_jm, "setBit",
211*6136Stomee "(I)Ljava/math/BigInteger;" },
212*6136Stomee
2131449Stomee /* java.lang.String */
2141449Stomee { JCLASS, &g_string_jc, "java/lang/String" },
2151449Stomee { JMETHOD, &g_strinit_bytes_jm, CONSTRUCTOR, "([B)V" },
2161449Stomee { JMETHOD, &g_strbytes_jm, "getBytes", "()[B" },
2171449Stomee { JMETHOD, &g_trim_jm, "trim", "()Ljava/lang/String;" },
2181449Stomee
2193645Stomee /* java.lang.StringBuilder */
2203645Stomee { JCLASS, &g_buf_jc, "java/lang/StringBuilder" },
2211449Stomee { JMETHOD, &g_bufinit_jm, CONSTRUCTOR, "()V" },
2221449Stomee { JMETHOD, &g_buf_append_char_jm, "append",
2233645Stomee "(C)Ljava/lang/StringBuilder;" },
2241449Stomee { JMETHOD, &g_buf_append_int_jm, "append",
2253645Stomee "(I)Ljava/lang/StringBuilder;" },
2261449Stomee { JMETHOD, &g_buf_append_long_jm, "append",
2273645Stomee "(J)Ljava/lang/StringBuilder;" },
2281449Stomee { JMETHOD, &g_buf_append_str_jm, "append",
2293645Stomee "(Ljava/lang/String;)Ljava/lang/StringBuilder;" },
2301449Stomee { JMETHOD, &g_buf_append_obj_jm, "append",
2313645Stomee "(Ljava/lang/Object;)Ljava/lang/StringBuilder;" },
2321449Stomee { JMETHOD, &g_buflen_jm, "length", "()I" },
2331449Stomee { JMETHOD, &g_bufsetlen_jm, "setLength", "(I)V" },
2341449Stomee
2351449Stomee /* java.lang.Object */
2361449Stomee { JCLASS, &g_object_jc, "java/lang/Object" },
2371449Stomee { JMETHOD, &g_tostring_jm, "toString",
2381449Stomee "()Ljava/lang/String;" },
2391449Stomee { JMETHOD, &g_equals_jm, "equals",
2401449Stomee "(Ljava/lang/Object;)Z" },
2411449Stomee
2421449Stomee /* java.lang.Enum */
2431449Stomee { JCLASS, &g_enum_jc, "java/lang/Enum" },
2441449Stomee { JMETHOD, &g_enumname_jm, "name",
2451449Stomee "()Ljava/lang/String;" },
2461449Stomee
2471449Stomee /* List */
2481449Stomee { JCLASS, &g_list_jc, "java/util/List" },
2491449Stomee { JMETHOD, &g_listclear_jm, "clear", "()V" },
2501449Stomee { JMETHOD, &g_listadd_jm, "add", "(Ljava/lang/Object;)Z" },
2511449Stomee { JMETHOD, &g_listget_jm, "get", "(I)Ljava/lang/Object;" },
2521449Stomee { JMETHOD, &g_listsize_jm, "size", "()I" },
2531449Stomee
2541449Stomee { DTJ_TYPE_END }
2551449Stomee };
2561449Stomee
2571449Stomee status = dtj_cache_jni_classes(jenv, table);
2581449Stomee if (status == DTJ_OK) {
2591449Stomee g_dtj_load_common = B_TRUE;
2601449Stomee }
2611449Stomee return (status);
2621449Stomee }
2631449Stomee
2641449Stomee static int
2651449Stomee /* ARGSUSED */
dtj_java_class_cmp(const void * v1,const void * v2,void * arg)2661449Stomee dtj_java_class_cmp(const void * v1, const void * v2, void *arg)
2671449Stomee {
2681449Stomee const dtj_java_class_t *c1 = v1;
2691449Stomee const dtj_java_class_t *c2 = v2;
2701449Stomee return (strcmp(c1->djc_name, c2->djc_name));
2711449Stomee }
2721449Stomee
2731449Stomee static int
2741449Stomee /* ARGSUSED */
dtj_java_method_cmp(const void * v1,const void * v2,void * arg)2751449Stomee dtj_java_method_cmp(const void *v1, const void *v2, void *arg)
2761449Stomee {
2771449Stomee int cmp;
2781449Stomee const dtj_java_method_t *m1 = v1;
2791449Stomee const dtj_java_method_t *m2 = v2;
2801449Stomee cmp = strcmp(m1->djm_name, m2->djm_name);
2811449Stomee if (cmp == 0) {
2821449Stomee cmp = strcmp(m1->djm_signature, m2->djm_signature);
2831449Stomee }
2841449Stomee return (cmp);
2851449Stomee }
2861449Stomee
2871449Stomee static int
2881449Stomee /* ARGSUSED */
dtj_java_field_cmp(const void * v1,const void * v2,void * arg)2891449Stomee dtj_java_field_cmp(const void *v1, const void *v2, void *arg)
2901449Stomee {
2911449Stomee const dtj_java_field_t *f1 = v1;
2921449Stomee const dtj_java_field_t *f2 = v2;
2931449Stomee return (strcmp(f1->djf_name, f2->djf_name));
2941449Stomee }
2951449Stomee
2961449Stomee 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)2971449Stomee dtj_java_class_create(JNIEnv *jenv, jclass *jc, char *name,
2981449Stomee uu_list_pool_t *classpool, uu_list_pool_t *methodpool,
2991449Stomee uu_list_pool_t *fieldpool)
3001449Stomee {
3011449Stomee dtj_java_class_t *c = uu_zalloc(sizeof (dtj_java_class_t));
3021449Stomee if (c) {
3031449Stomee uu_list_node_init(c, &c->djc_node, classpool);
3041449Stomee c->djc_ptr = jc;
3051449Stomee c->djc_name = name;
3061449Stomee c->djc_methods = uu_list_create(methodpool, NULL,
3071449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
3081449Stomee if (!c->djc_methods) {
3091449Stomee dtj_throw_out_of_memory(jenv,
3101449Stomee "Failed method list creation");
3111449Stomee uu_list_node_fini(c, &c->djc_node, classpool);
3121449Stomee free(c);
3131449Stomee c = NULL;
3141449Stomee }
3151449Stomee c->djc_fields = uu_list_create(fieldpool, NULL,
3161449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
3171449Stomee if (!c->djc_fields) {
3181449Stomee dtj_throw_out_of_memory(jenv,
3191449Stomee "Failed field list creation");
3201449Stomee uu_list_destroy(c->djc_methods);
3211449Stomee c->djc_methods = NULL;
3221449Stomee uu_list_node_fini(c, &c->djc_node, classpool);
3231449Stomee free(c);
3241449Stomee c = NULL;
3251449Stomee }
3261449Stomee } else {
3271449Stomee dtj_throw_out_of_memory(jenv,
3281449Stomee "Failed to allocate class description");
3291449Stomee }
3301449Stomee return (c);
3311449Stomee }
3321449Stomee
3331449Stomee static dtj_java_method_t *
dtj_java_method_create(JNIEnv * jenv,jmethodID * jm,char * name,char * signature,uu_list_pool_t * methodpool)3341449Stomee dtj_java_method_create(JNIEnv *jenv, jmethodID *jm, char *name, char *signature,
3351449Stomee uu_list_pool_t *methodpool)
3361449Stomee {
3371449Stomee dtj_java_method_t *m = uu_zalloc(sizeof (dtj_java_method_t));
3381449Stomee if (m) {
3391449Stomee uu_list_node_init(m, &m->djm_node, methodpool);
3401449Stomee m->djm_ptr = jm;
3411449Stomee m->djm_name = name;
3421449Stomee m->djm_signature = signature;
3431449Stomee m->djm_static = B_FALSE;
3441449Stomee } else {
3451449Stomee dtj_throw_out_of_memory(jenv,
3461449Stomee "Failed to allocate method description");
3471449Stomee }
3481449Stomee return (m);
3491449Stomee }
3501449Stomee
3511449Stomee static dtj_java_method_t *
dtj_java_static_method_create(JNIEnv * jenv,jmethodID * jm,char * name,char * signature,uu_list_pool_t * methodpool)3521449Stomee dtj_java_static_method_create(JNIEnv *jenv, jmethodID *jm, char *name,
3531449Stomee char *signature, uu_list_pool_t *methodpool)
3541449Stomee {
3551449Stomee dtj_java_method_t *m = dtj_java_method_create(jenv, jm, name, signature,
3561449Stomee methodpool);
3571449Stomee if (m) {
3581449Stomee m->djm_static = B_TRUE;
3591449Stomee }
3601449Stomee return (m);
3611449Stomee }
3621449Stomee
3631449Stomee static dtj_java_field_t *
dtj_java_field_create(JNIEnv * jenv,jfieldID * jf,char * name,char * type,uu_list_pool_t * fieldpool)3641449Stomee dtj_java_field_create(JNIEnv *jenv, jfieldID *jf, char *name, char *type,
3651449Stomee uu_list_pool_t *fieldpool)
3661449Stomee {
3671449Stomee dtj_java_field_t *f = uu_zalloc(sizeof (dtj_java_field_t));
3681449Stomee if (f) {
3691449Stomee uu_list_node_init(f, &f->djf_node, fieldpool);
3701449Stomee f->djf_ptr = jf;
3711449Stomee f->djf_name = name;
3721449Stomee f->djf_type = type;
3731449Stomee f->djf_static = B_FALSE;
3741449Stomee } else {
3751449Stomee dtj_throw_out_of_memory(jenv,
3761449Stomee "Failed to allocate field description");
3771449Stomee }
3781449Stomee return (f);
3791449Stomee }
3801449Stomee
3811449Stomee static dtj_java_field_t *
dtj_java_static_field_create(JNIEnv * jenv,jfieldID * jf,char * name,char * type,uu_list_pool_t * fieldpool)3821449Stomee dtj_java_static_field_create(JNIEnv *jenv, jfieldID *jf, char *name, char *type,
3831449Stomee uu_list_pool_t *fieldpool)
3841449Stomee {
3851449Stomee dtj_java_field_t *f = dtj_java_field_create(jenv, jf, name, type,
3861449Stomee fieldpool);
3871449Stomee if (f) {
3881449Stomee f->djf_static = B_TRUE;
3891449Stomee }
3901449Stomee return (f);
3911449Stomee }
3921449Stomee
3931449Stomee static void
3941449Stomee /* ARGSUSED */
dtj_java_class_destroy(void * v,void * arg)3951449Stomee dtj_java_class_destroy(void *v, void *arg)
3961449Stomee {
3971449Stomee if (v) {
3981449Stomee dtj_java_class_t *c = v;
3991449Stomee c->djc_ptr = NULL; /* do not free user-defined storage */
4001449Stomee c->djc_name = NULL; /* string literal */
4011449Stomee dtj_list_destroy(c->djc_methods, dtj_java_method_destroy, NULL);
4021449Stomee dtj_list_destroy(c->djc_fields, dtj_java_field_destroy, NULL);
4031449Stomee c->djc_methods = NULL;
4041449Stomee c->djc_fields = NULL;
4051449Stomee uu_free(v);
4061449Stomee }
4071449Stomee }
4081449Stomee
4091449Stomee static void
4101449Stomee /* ARGSUSED */
dtj_java_method_destroy(void * v,void * arg)4111449Stomee dtj_java_method_destroy(void *v, void *arg)
4121449Stomee {
4131449Stomee if (v) {
4141449Stomee dtj_java_method_t *m = v;
4151449Stomee m->djm_ptr = NULL; /* do not free user-defined space */
4161449Stomee m->djm_name = NULL; /* string literal */
4171449Stomee m->djm_signature = NULL; /* string literal */
4181449Stomee uu_free(v);
4191449Stomee }
4201449Stomee }
4211449Stomee
4221449Stomee static void
4231449Stomee /* ARGSUSED */
dtj_java_field_destroy(void * v,void * arg)4241449Stomee dtj_java_field_destroy(void *v, void *arg)
4251449Stomee {
4261449Stomee if (v) {
4271449Stomee dtj_java_field_t *f = v;
4281449Stomee f->djf_ptr = NULL; /* do not free user-defined space */
4291449Stomee f->djf_name = NULL; /* string literal */
4301449Stomee f->djf_type = NULL; /* string literal */
4311449Stomee uu_free(f);
4321449Stomee }
4331449Stomee }
4341449Stomee
4351449Stomee dtj_status_t
dtj_cache_jni_classes(JNIEnv * jenv,const dtj_table_entry_t * table)4361449Stomee dtj_cache_jni_classes(JNIEnv *jenv, const dtj_table_entry_t *table)
4371449Stomee {
4381449Stomee dtj_java_class_t *class;
4391449Stomee uu_list_pool_t *classpool;
4401449Stomee uu_list_pool_t *methodpool;
4411449Stomee uu_list_pool_t *fieldpool;
4421449Stomee uu_list_t *classes;
4431449Stomee uu_list_walk_t *itr;
4441449Stomee jclass jc;
4451449Stomee jclass gjc;
4461449Stomee dtj_status_t status;
4471449Stomee
4481449Stomee classpool = uu_list_pool_create("classpool",
4491449Stomee sizeof (dtj_java_class_t),
4501449Stomee offsetof(dtj_java_class_t, djc_node), dtj_java_class_cmp,
4511449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
4521449Stomee if (!classpool) {
4531449Stomee dtj_throw_out_of_memory(jenv, "failed class pool creation");
4541449Stomee return (DTJ_ERR);
4551449Stomee }
4561449Stomee methodpool = uu_list_pool_create("methodpool",
4571449Stomee sizeof (dtj_java_method_t),
4581449Stomee offsetof(dtj_java_method_t, djm_node), dtj_java_method_cmp,
4591449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
4601449Stomee if (!methodpool) {
4611449Stomee dtj_throw_out_of_memory(jenv, "failed method pool creation");
4621449Stomee return (DTJ_ERR);
4631449Stomee }
4641449Stomee fieldpool = uu_list_pool_create("fieldpool",
4651449Stomee sizeof (dtj_java_field_t),
4661449Stomee offsetof(dtj_java_field_t, djf_node), dtj_java_field_cmp,
4671449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
4681449Stomee if (!fieldpool) {
4691449Stomee dtj_throw_out_of_memory(jenv, "failed field pool creation");
4701449Stomee return (DTJ_ERR);
4711449Stomee }
4721449Stomee
4731449Stomee classes = uu_list_create(classpool, NULL,
4741449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
4751449Stomee if (!classes) {
4761449Stomee dtj_throw_out_of_memory(jenv, "failed class list creation");
4771449Stomee return (DTJ_ERR);
4781449Stomee }
4791449Stomee
4801449Stomee status = dtj_get_jni_classes(jenv, classes, classpool, methodpool,
4811449Stomee fieldpool, table);
4821449Stomee if (status != DTJ_OK) {
4831449Stomee /* java error pending */
4841449Stomee return (status);
4851449Stomee }
4861449Stomee
4871449Stomee itr = uu_list_walk_start(classes, 0);
4881449Stomee while ((class = uu_list_walk_next(itr)) != NULL) {
4891449Stomee jc = (*jenv)->FindClass(jenv, class->djc_name);
4901449Stomee if (!jc) {
4911449Stomee /* NoClassDefFoundError pending */
4921449Stomee return (DTJ_ERR);
4931449Stomee }
4941449Stomee gjc = (*jenv)->NewGlobalRef(jenv, jc);
4951449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
4961449Stomee if (!gjc) {
4971449Stomee dtj_throw_out_of_memory(jenv,
4981449Stomee "Failed to create global class reference");
4991449Stomee return (DTJ_ERR);
5001449Stomee }
5011449Stomee *(class->djc_ptr) = gjc;
5021449Stomee status = dtj_cache_jni_methods(jenv, class);
5031449Stomee if (status != DTJ_OK) {
5041449Stomee /* java error pending */
5051449Stomee return (status);
5061449Stomee }
5071449Stomee status = dtj_cache_jni_fields(jenv, class);
5081449Stomee if (status != DTJ_OK) {
5091449Stomee /* java error pending */
5101449Stomee return (status);
5111449Stomee }
5121449Stomee }
5131449Stomee uu_list_walk_end(itr);
5141449Stomee dtj_list_destroy(classes, dtj_java_class_destroy, NULL);
5151449Stomee uu_list_pool_destroy(classpool);
5161449Stomee uu_list_pool_destroy(methodpool);
5171449Stomee uu_list_pool_destroy(fieldpool);
5181449Stomee return (DTJ_OK);
5191449Stomee }
5201449Stomee
5211449Stomee /*
5221449Stomee * Converts JNI table entry desriptions into java_class_t descriptors.
5231449Stomee */
5241449Stomee 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)5251449Stomee dtj_get_jni_classes(JNIEnv *jenv, uu_list_t *classes,
5261449Stomee uu_list_pool_t *classpool, uu_list_pool_t *methodpool,
5271449Stomee uu_list_pool_t *fieldpool, const dtj_table_entry_t *table)
5281449Stomee {
5291449Stomee int i;
5301449Stomee dtj_java_class_t *c = NULL;
5311449Stomee dtj_java_method_t *m;
5321449Stomee dtj_java_field_t *f;
5331449Stomee
5341449Stomee for (i = 0; table[i].djte_type != DTJ_TYPE_END; ++i) {
5351449Stomee /*
5361449Stomee * Class not added until all of its method and field information
5371449Stomee * is attached, so we defer adding a class until the next
5381449Stomee * element with type JCLASS.
5391449Stomee */
5401449Stomee switch (table[i].djte_type) {
5411449Stomee case JCLASS:
5421449Stomee if (c) {
5431449Stomee /* previous class */
5441449Stomee if (!dtj_list_add(classes, c)) {
5451449Stomee dtj_throw_out_of_memory(jenv,
5461449Stomee "Failed to add class description");
5471449Stomee /*
5481449Stomee * In response to an error return value,
5491449Stomee * the caller will delete the class
5501449Stomee * descriptions list with any
5511449Stomee * descriptions created so far.
5521449Stomee */
5531449Stomee return (DTJ_ERR);
5541449Stomee }
5551449Stomee }
5561449Stomee c = dtj_java_class_create(jenv,
5571449Stomee (jclass *)table[i].djte_addr, table[i].djte_name,
5581449Stomee classpool, methodpool, fieldpool);
5591449Stomee if (!c) {
5601449Stomee /* OutOfMemoryError pending */
5611449Stomee return (DTJ_ERR);
5621449Stomee }
5631449Stomee break;
5641449Stomee case JMETHOD:
5651449Stomee if (!c) {
5661449Stomee dtj_throw_illegal_state(jenv,
5671449Stomee "method description not preceded "
5681449Stomee "by class description");
5691449Stomee return (DTJ_ERR);
5701449Stomee }
5711449Stomee m = dtj_java_method_create(jenv,
5721449Stomee (jmethodID *)table[i].djte_addr,
5731449Stomee table[i].djte_name, table[i].djte_desc,
5741449Stomee methodpool);
5751449Stomee if (!m) {
5761449Stomee /* OutOfMemoryError pending */
5771449Stomee return (DTJ_ERR);
5781449Stomee }
5791449Stomee if (!dtj_list_add(c->djc_methods, m)) {
5801449Stomee dtj_throw_out_of_memory(jenv,
5811449Stomee "Failed to add method description");
5821449Stomee return (DTJ_ERR);
5831449Stomee }
5841449Stomee break;
5851449Stomee case JMETHOD_STATIC:
5861449Stomee if (!c) {
5871449Stomee dtj_throw_illegal_state(jenv,
5881449Stomee "static method description not preceded "
5891449Stomee "by class description");
5901449Stomee return (DTJ_ERR);
5911449Stomee }
5921449Stomee m = dtj_java_static_method_create(jenv,
5931449Stomee (jmethodID *)table[i].djte_addr,
5941449Stomee table[i].djte_name, table[i].djte_desc,
5951449Stomee methodpool);
5961449Stomee if (!m) {
5971449Stomee /* OutOfMemoryError pending */
5981449Stomee return (DTJ_ERR);
5991449Stomee }
6001449Stomee if (!dtj_list_add(c->djc_methods, m)) {
6011449Stomee dtj_throw_out_of_memory(jenv,
6021449Stomee "Failed to add static method description");
6031449Stomee return (DTJ_ERR);
6041449Stomee }
6051449Stomee break;
6061449Stomee case JFIELD:
6071449Stomee if (!c) {
6081449Stomee dtj_throw_illegal_state(jenv,
6091449Stomee "field description not preceded "
6101449Stomee "by class description");
6111449Stomee return (DTJ_ERR);
6121449Stomee }
6131449Stomee f = dtj_java_field_create(jenv,
6141449Stomee (jfieldID *)table[i].djte_addr,
6151449Stomee table[i].djte_name, table[i].djte_desc,
6161449Stomee fieldpool);
6171449Stomee if (!f) {
6181449Stomee /* OutOfMemoryError pending */
6191449Stomee return (DTJ_ERR);
6201449Stomee }
6211449Stomee if (!dtj_list_add(c->djc_fields, f)) {
6221449Stomee dtj_throw_out_of_memory(jenv,
6231449Stomee "Failed to add field description");
6241449Stomee return (DTJ_ERR);
6251449Stomee }
6261449Stomee break;
6271449Stomee case JFIELD_STATIC:
6281449Stomee if (!c) {
6291449Stomee dtj_throw_illegal_state(jenv,
6301449Stomee "static field description not preceded "
6311449Stomee "by class description");
6321449Stomee return (DTJ_ERR);
6331449Stomee }
6341449Stomee f = dtj_java_static_field_create(jenv,
6351449Stomee (jfieldID *)table[i].djte_addr,
6361449Stomee table[i].djte_name, table[i].djte_desc,
6371449Stomee fieldpool);
6381449Stomee if (!f) {
6391449Stomee /* OutOfMemoryError pending */
6401449Stomee return (DTJ_ERR);
6411449Stomee }
6421449Stomee if (!dtj_list_add(c->djc_fields, f)) {
6431449Stomee dtj_throw_out_of_memory(jenv,
6441449Stomee "Failed to add static field description");
6451449Stomee return (DTJ_ERR);
6461449Stomee }
6471449Stomee break;
6481449Stomee default:
6491449Stomee dtj_throw_illegal_state(jenv,
6501449Stomee "Unexpected jni_type_e: %d", table[i].djte_type);
6511449Stomee return (DTJ_ERR);
6521449Stomee }
6531449Stomee }
6541449Stomee if (c) {
6551449Stomee /* last class */
6561449Stomee if (!dtj_list_add(classes, c)) {
6571449Stomee dtj_throw_out_of_memory(jenv,
6581449Stomee "Failed to add class description");
6591449Stomee return (DTJ_ERR);
6601449Stomee }
6611449Stomee }
6621449Stomee
6631449Stomee return (DTJ_OK);
6641449Stomee }
6651449Stomee
6661449Stomee static dtj_status_t
dtj_cache_jni_methods(JNIEnv * jenv,dtj_java_class_t * c)6671449Stomee dtj_cache_jni_methods(JNIEnv *jenv, dtj_java_class_t *c)
6681449Stomee {
6691449Stomee dtj_java_method_t *method;
6701449Stomee jmethodID jm;
6711449Stomee uu_list_walk_t *itr;
6721449Stomee itr = uu_list_walk_start(c->djc_methods, 0);
6731449Stomee while ((method = uu_list_walk_next(itr)) != NULL) {
6741449Stomee if (method->djm_static) {
6751449Stomee jm = (*jenv)->GetStaticMethodID(jenv, *(c->djc_ptr),
6761449Stomee method->djm_name, method->djm_signature);
6771449Stomee } else {
6781449Stomee jm = (*jenv)->GetMethodID(jenv, *(c->djc_ptr),
6791449Stomee method->djm_name, method->djm_signature);
6801449Stomee }
6811449Stomee if (jm == 0) {
6821449Stomee /*
6831449Stomee * The pending NoSuchMethodError gives only the
6841449Stomee * method name, which is not so helpful for
6851449Stomee * overloaded methods and methods such as <init>
6861449Stomee * that have the same name in multiple classes.
6871449Stomee * Clear the pending error and throw one that
6881449Stomee * includes the class name and the method
6891449Stomee * signature.
6901449Stomee */
6911449Stomee jclass jc;
6921449Stomee char msg[DTJ_MSG_SIZE];
6931449Stomee (*jenv)->ExceptionClear(jenv);
6941449Stomee (void) snprintf(msg, sizeof (msg), "%s %s %s",
6951449Stomee c->djc_name, method->djm_name,
6961449Stomee method->djm_signature);
6971449Stomee
6981449Stomee jc = (*jenv)->FindClass(jenv,
6991449Stomee "java/lang/NoSuchMethodError");
7001449Stomee (*jenv)->ThrowNew(jenv, jc, msg);
7011449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
7021449Stomee return (DTJ_ERR);
7031449Stomee }
7041449Stomee *(method->djm_ptr) = jm;
7051449Stomee }
7061449Stomee uu_list_walk_end(itr);
7071449Stomee return (DTJ_OK);
7081449Stomee }
7091449Stomee
7101449Stomee static dtj_status_t
dtj_cache_jni_fields(JNIEnv * jenv,dtj_java_class_t * c)7111449Stomee dtj_cache_jni_fields(JNIEnv *jenv, dtj_java_class_t *c)
7121449Stomee {
7131449Stomee dtj_java_field_t *field;
7141449Stomee jfieldID jf;
7151449Stomee uu_list_walk_t *itr;
7161449Stomee itr = uu_list_walk_start(c->djc_fields, 0);
7171449Stomee while ((field = uu_list_walk_next(itr)) != NULL) {
7181449Stomee if (field->djf_static) {
7191449Stomee jf = (*jenv)->GetStaticFieldID(jenv, *(c->djc_ptr),
7201449Stomee field->djf_name, field->djf_type);
7211449Stomee } else {
7221449Stomee jf = (*jenv)->GetFieldID(jenv, *(c->djc_ptr),
7231449Stomee field->djf_name, field->djf_type);
7241449Stomee }
7251449Stomee if (jf == 0) {
7261449Stomee jclass jc;
7271449Stomee char msg[DTJ_MSG_SIZE];
7281449Stomee (*jenv)->ExceptionClear(jenv);
7291449Stomee (void) snprintf(msg, sizeof (msg),
7301449Stomee "%s.%s signature: %s", c->djc_name,
7311449Stomee field->djf_name, field->djf_type);
7321449Stomee
7331449Stomee jc = (*jenv)->FindClass(jenv,
7341449Stomee "java/lang/NoSuchFieldError");
7351449Stomee (*jenv)->ThrowNew(jenv, jc, msg);
7361449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
7371449Stomee return (DTJ_ERR);
7381449Stomee }
7391449Stomee *(field->djf_ptr) = jf;
7401449Stomee }
7411449Stomee uu_list_walk_end(itr);
7421449Stomee return (DTJ_OK);
7431449Stomee }
7441449Stomee
7451449Stomee
7461449Stomee /* Common utilities */
7471449Stomee
7481449Stomee static void
dtj_throw(JNIEnv * jenv,jclass jc,const char * fmt,va_list * ap)7491449Stomee dtj_throw(JNIEnv *jenv, jclass jc, const char *fmt, va_list *ap)
7501449Stomee {
7511449Stomee char msg[DTJ_MSG_SIZE];
7521449Stomee (void) vsnprintf(msg, sizeof (msg), fmt, *ap);
7531449Stomee (*jenv)->ThrowNew(jenv, jc, msg);
7541449Stomee }
7551449Stomee
7561449Stomee void
dtj_throw_out_of_memory(JNIEnv * jenv,const char * fmt,...)7571449Stomee dtj_throw_out_of_memory(JNIEnv *jenv, const char *fmt, ...)
7581449Stomee {
7591449Stomee va_list ap;
7601449Stomee jclass jc;
7611449Stomee /*
7621449Stomee * JNI documentation unclear whether NewGlobalRef() can throw
7631449Stomee * OutOfMemoryError, so we'll make this function safe in case
7641449Stomee * OutOfMemoryError has already been thrown
7651449Stomee */
7661449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
7671449Stomee return;
7681449Stomee }
7691449Stomee jc = (*jenv)->FindClass(jenv,
7701449Stomee "java/lang/OutOfMemoryError");
7711449Stomee va_start(ap, fmt);
7721449Stomee dtj_throw(jenv, jc, fmt, &ap);
7731449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
7741449Stomee va_end(ap);
7751449Stomee }
7761449Stomee
7771449Stomee void
dtj_throw_null_pointer(JNIEnv * jenv,const char * fmt,...)7781449Stomee dtj_throw_null_pointer(JNIEnv *jenv, const char *fmt, ...)
7791449Stomee {
7801449Stomee va_list ap;
7811449Stomee jclass jc = (*jenv)->FindClass(jenv,
7821449Stomee "java/lang/NullPointerException");
7831449Stomee va_start(ap, fmt);
7841449Stomee dtj_throw(jenv, jc, fmt, &ap);
7851449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
7861449Stomee va_end(ap);
7871449Stomee }
7881449Stomee
7891449Stomee void
dtj_throw_illegal_state(JNIEnv * jenv,const char * fmt,...)7901449Stomee dtj_throw_illegal_state(JNIEnv *jenv, const char *fmt, ...)
7911449Stomee {
7921449Stomee va_list ap;
7931449Stomee jclass jc = (*jenv)->FindClass(jenv,
7941449Stomee "java/lang/IllegalStateException");
7951449Stomee va_start(ap, fmt);
7961449Stomee dtj_throw(jenv, jc, fmt, &ap);
7971449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
7981449Stomee va_end(ap);
7991449Stomee }
8001449Stomee
8011449Stomee void
dtj_throw_illegal_argument(JNIEnv * jenv,const char * fmt,...)8021449Stomee dtj_throw_illegal_argument(JNIEnv *jenv, const char *fmt, ...)
8031449Stomee {
8041449Stomee va_list ap;
8051449Stomee jclass jc = (*jenv)->FindClass(jenv,
8061449Stomee "java/lang/IllegalArgumentException");
8071449Stomee va_start(ap, fmt);
8081449Stomee dtj_throw(jenv, jc, fmt, &ap);
8091449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
8101449Stomee va_end(ap);
8111449Stomee }
8121449Stomee
8131449Stomee void
dtj_throw_no_such_element(JNIEnv * jenv,const char * fmt,...)8141449Stomee dtj_throw_no_such_element(JNIEnv *jenv, const char *fmt, ...)
8151449Stomee {
8161449Stomee va_list ap;
8171449Stomee jclass jc = (*jenv)->FindClass(jenv,
8181449Stomee "java/util/NoSuchElementException");
8191449Stomee va_start(ap, fmt);
8201449Stomee dtj_throw(jenv, jc, fmt, &ap);
8211449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
8221449Stomee va_end(ap);
8231449Stomee }
8241449Stomee
8251449Stomee void
dtj_throw_class_cast(JNIEnv * jenv,const char * fmt,...)8261449Stomee dtj_throw_class_cast(JNIEnv *jenv, const char *fmt, ...)
8271449Stomee {
8281449Stomee va_list ap;
8291449Stomee jclass jc = (*jenv)->FindClass(jenv,
8301449Stomee "java/lang/ClassCastException");
8311449Stomee va_start(ap, fmt);
8321449Stomee dtj_throw(jenv, jc, fmt, &ap);
8331449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
8341449Stomee va_end(ap);
8351449Stomee }
8361449Stomee
8371449Stomee void
dtj_throw_assertion(JNIEnv * jenv,const char * fmt,...)8381449Stomee dtj_throw_assertion(JNIEnv *jenv, const char *fmt, ...)
8391449Stomee {
8401449Stomee va_list ap;
8411449Stomee jclass jc = (*jenv)->FindClass(jenv,
8421449Stomee "java/lang/AssertionError");
8431449Stomee va_start(ap, fmt);
8441449Stomee dtj_throw(jenv, jc, fmt, &ap);
8451449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
8461449Stomee va_end(ap);
8471449Stomee }
8481449Stomee
8491449Stomee void
dtj_throw_resource_limit(JNIEnv * jenv,const char * fmt,...)8501449Stomee dtj_throw_resource_limit(JNIEnv *jenv, const char *fmt, ...)
8511449Stomee {
8521449Stomee va_list ap;
8531449Stomee jclass jc = (*jenv)->FindClass(jenv,
8541449Stomee "org/opensolaris/os/dtrace/ResourceLimitException");
8551449Stomee va_start(ap, fmt);
8561449Stomee dtj_throw(jenv, jc, fmt, &ap);
8571449Stomee (*jenv)->DeleteLocalRef(jenv, jc);
8581449Stomee va_end(ap);
8591449Stomee }
8601449Stomee
8611449Stomee void
dtj_wrap_exception(JNIEnv * jenv,const char * file,int line)8621449Stomee dtj_wrap_exception(JNIEnv *jenv, const char *file, int line)
8631449Stomee {
8641449Stomee jthrowable e = NULL;
8651449Stomee jthrowable nx = NULL;
8661449Stomee jstring jfile = NULL;
8671449Stomee
8681449Stomee e = (*jenv)->ExceptionOccurred(jenv);
8691449Stomee if (!e) {
8701449Stomee return;
8711449Stomee }
8721449Stomee
8731449Stomee if (!g_dtj_load_common) {
8741449Stomee return;
8751449Stomee }
8761449Stomee
8771449Stomee (*jenv)->ExceptionClear(jenv);
8781449Stomee
8791449Stomee /* Unsafe to test while exception pending */
8801449Stomee if ((*jenv)->IsInstanceOf(jenv, e, g_nx_jc)) {
8811449Stomee /* Already wrapped */
8821449Stomee (*jenv)->Throw(jenv, e);
8831449Stomee (*jenv)->DeleteLocalRef(jenv, e);
8841449Stomee return;
8851449Stomee }
8861449Stomee
8871449Stomee jfile = dtj_NewStringNative(jenv, file);
8881449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
8891449Stomee /*
8901449Stomee * Only wrap the exception if possible, otherwise just throw the
8911449Stomee * original exception.
8921449Stomee */
8931449Stomee (*jenv)->ExceptionClear(jenv);
8941449Stomee (*jenv)->Throw(jenv, e);
8951449Stomee (*jenv)->DeleteLocalRef(jenv, e);
8961449Stomee return;
8971449Stomee }
8981449Stomee
8991449Stomee nx = (jthrowable)(*jenv)->NewObject(jenv, g_nx_jc, g_nxinit_jm,
9001449Stomee jfile, line, e);
9011449Stomee (*jenv)->DeleteLocalRef(jenv, jfile);
9021449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
9031449Stomee (*jenv)->ExceptionClear(jenv);
9041449Stomee (*jenv)->Throw(jenv, e);
9051449Stomee (*jenv)->DeleteLocalRef(jenv, e);
9061449Stomee return;
9071449Stomee }
9081449Stomee
9091449Stomee (*jenv)->DeleteLocalRef(jenv, e);
9101449Stomee (*jenv)->Throw(jenv, nx);
9111449Stomee (*jenv)->DeleteLocalRef(jenv, nx);
9121449Stomee }
9131449Stomee
9141449Stomee /*
9151449Stomee * Calls the given java object's toString() method and prints the value to
9161449Stomee * stdout. Useful for debugging. Guaranteed that no exception is pending when
9171449Stomee * this function returns.
9181449Stomee */
9191449Stomee void
dtj_print_object(JNIEnv * jenv,jobject jobj)9201449Stomee dtj_print_object(JNIEnv *jenv, jobject jobj)
9211449Stomee {
9221449Stomee jstring jstr;
9231449Stomee const char *cstr;
9241449Stomee
9251449Stomee if (!g_dtj_load_common) {
9261449Stomee dtj_throw_illegal_state(jenv,
9271449Stomee "dtj_load_common() has not been called");
9281449Stomee (*jenv)->ExceptionDescribe(jenv); /* clears the exception */
9291449Stomee return;
9301449Stomee }
9311449Stomee
9321449Stomee if (!jobj) {
9331449Stomee (void) printf("null\n");
9341449Stomee return;
9351449Stomee }
9361449Stomee
9371449Stomee jstr = (*jenv)->CallObjectMethod(jenv, jobj, g_tostring_jm);
9381449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
9391449Stomee (*jenv)->ExceptionDescribe(jenv); /* clears the exception */
9401449Stomee return;
9411449Stomee }
9421449Stomee cstr = (*jenv)->GetStringUTFChars(jenv, jstr, 0);
9431449Stomee if (cstr) {
9441449Stomee (void) printf("%s\n", cstr);
9451449Stomee } else {
9461449Stomee (*jenv)->ExceptionDescribe(jenv); /* clears the exception */
9471449Stomee (*jenv)->DeleteLocalRef(jenv, jstr);
9481449Stomee return;
9491449Stomee }
9501449Stomee (*jenv)->ReleaseStringUTFChars(jenv, jstr, cstr);
9511449Stomee (*jenv)->DeleteLocalRef(jenv, jstr);
9521449Stomee }
9531449Stomee
954*6136Stomee jobject
dtj_uint64(JNIEnv * jenv,uint64_t u)955*6136Stomee dtj_uint64(JNIEnv *jenv, uint64_t u)
956*6136Stomee {
957*6136Stomee int64_t i = (int64_t)u;
958*6136Stomee jobject val64;
959*6136Stomee
960*6136Stomee if (i >= 0) {
961*6136Stomee val64 = (*jenv)->CallStaticObjectMethod(jenv, g_bigint_jc,
962*6136Stomee g_bigint_val_jsm, u);
963*6136Stomee } else {
964*6136Stomee jobject tmp;
965*6136Stomee
966*6136Stomee u ^= ((uint64_t)0x1 << 63);
967*6136Stomee val64 = (*jenv)->CallStaticObjectMethod(jenv, g_bigint_jc,
968*6136Stomee g_bigint_val_jsm, u);
969*6136Stomee tmp = val64;
970*6136Stomee val64 = (*jenv)->CallObjectMethod(jenv, tmp,
971*6136Stomee g_bigint_setbit_jm, 63);
972*6136Stomee (*jenv)->DeleteLocalRef(jenv, tmp);
973*6136Stomee }
974*6136Stomee
975*6136Stomee return (val64);
976*6136Stomee }
977*6136Stomee
978*6136Stomee jobject
dtj_int128(JNIEnv * jenv,uint64_t high,uint64_t low)979*6136Stomee dtj_int128(JNIEnv *jenv, uint64_t high, uint64_t low)
980*6136Stomee {
981*6136Stomee jobject val128;
982*6136Stomee jobject low64;
983*6136Stomee jobject tmp;
984*6136Stomee
985*6136Stomee val128 = (*jenv)->CallStaticObjectMethod(jenv, g_bigint_jc,
986*6136Stomee g_bigint_val_jsm, high);
987*6136Stomee tmp = val128;
988*6136Stomee val128 = (*jenv)->CallObjectMethod(jenv, tmp, g_bigint_shl_jm, 64);
989*6136Stomee (*jenv)->DeleteLocalRef(jenv, tmp);
990*6136Stomee low64 = dtj_uint64(jenv, low);
991*6136Stomee tmp = val128;
992*6136Stomee val128 = (*jenv)->CallObjectMethod(jenv, tmp, g_bigint_or_jm, low64);
993*6136Stomee (*jenv)->DeleteLocalRef(jenv, tmp);
994*6136Stomee (*jenv)->DeleteLocalRef(jenv, low64);
995*6136Stomee
996*6136Stomee return (val128);
997*6136Stomee }
998*6136Stomee
9991449Stomee jstring
dtj_format_string(JNIEnv * jenv,const char * fmt,...)10001449Stomee dtj_format_string(JNIEnv *jenv, const char *fmt, ...)
10011449Stomee {
10021449Stomee va_list ap;
10031449Stomee char str[DTJ_MSG_SIZE];
10041449Stomee
10051449Stomee jstring jstr = NULL;
10061449Stomee
10071449Stomee va_start(ap, fmt);
10081449Stomee (void) vsnprintf(str, sizeof (str), fmt, ap);
10091449Stomee va_end(ap);
10101449Stomee
10111449Stomee jstr = dtj_NewStringNative(jenv, str);
10121449Stomee /* return NULL if OutOfMemoryError pending */
10131449Stomee return (jstr);
10141449Stomee }
10151449Stomee
10161449Stomee jstring
dtj_NewStringNative(JNIEnv * jenv,const char * str)10171449Stomee dtj_NewStringNative(JNIEnv *jenv, const char *str)
10181449Stomee {
10191449Stomee jstring result;
10201449Stomee jbyteArray bytes = 0;
10211449Stomee int len;
10221449Stomee
10231449Stomee if (!g_dtj_load_common) {
10241449Stomee dtj_throw_illegal_state(jenv,
10251449Stomee "dtj_load_common() has not been called");
10261449Stomee return (NULL);
10271449Stomee }
10281449Stomee
10291449Stomee len = strlen(str);
10301449Stomee
10311449Stomee bytes = (*jenv)->NewByteArray(jenv, len);
10321449Stomee if (!bytes) {
10331449Stomee return (NULL); /* OutOfMemoryError pending */
10341449Stomee }
10351449Stomee (*jenv)->SetByteArrayRegion(jenv, bytes, 0, len,
10361449Stomee (jbyte *)str);
10371449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
10381449Stomee (*jenv)->DeleteLocalRef(jenv, bytes);
10391449Stomee return (NULL); /* ArrayIndexOutOfBoundsException pending */
10401449Stomee }
10411449Stomee result = (*jenv)->NewObject(jenv, g_string_jc, g_strinit_bytes_jm,
10421449Stomee bytes);
10431449Stomee (*jenv)->DeleteLocalRef(jenv, bytes);
10441449Stomee /* return NULL result if exception pending */
10451449Stomee return (result);
10461449Stomee }
10471449Stomee
10481449Stomee char *
dtj_GetStringNativeChars(JNIEnv * jenv,jstring jstr)10491449Stomee dtj_GetStringNativeChars(JNIEnv *jenv, jstring jstr)
10501449Stomee {
10511449Stomee jbyteArray bytes = NULL;
10521449Stomee
10531449Stomee jint len;
10541449Stomee char *result = NULL;
10551449Stomee
10561449Stomee if (!g_dtj_load_common) {
10571449Stomee dtj_throw_illegal_state(jenv,
10581449Stomee "dtj_load_common() has not been called");
10591449Stomee return (NULL);
10601449Stomee }
10611449Stomee
10621449Stomee bytes = (*jenv)->CallObjectMethod(jenv, jstr, g_strbytes_jm);
10631449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
10641449Stomee return (NULL); /* OutOfMemoryError pending */
10651449Stomee }
10661449Stomee /* Does not throw exceptions */
10671449Stomee len = (*jenv)->GetArrayLength(jenv, bytes);
10681449Stomee result = malloc(len + 1);
10691449Stomee if (!result) {
10701449Stomee (*jenv)->DeleteLocalRef(jenv, bytes);
10711449Stomee dtj_throw_out_of_memory(jenv,
10721449Stomee "could not allocate native chars");
10731449Stomee return (NULL);
10741449Stomee }
10751449Stomee
10761449Stomee /* Skip check for ArrayIndexOutOfBoundsException */
10771449Stomee (*jenv)->GetByteArrayRegion(jenv, bytes, 0, len,
10781449Stomee (jbyte *)result);
10791449Stomee (*jenv)->DeleteLocalRef(jenv, bytes);
10801449Stomee result[len] = '\0'; /* NUL-terminate */
10811449Stomee
10821449Stomee return (result);
10831449Stomee }
10841449Stomee
10851449Stomee void
10861449Stomee /* ARGSUSED */
dtj_ReleaseStringNativeChars(JNIEnv * jenv,jstring jstr,const char * str)10871449Stomee dtj_ReleaseStringNativeChars(JNIEnv *jenv, jstring jstr, const char *str)
10881449Stomee {
10891449Stomee free((void *)str);
10901449Stomee }
10911449Stomee
10921449Stomee char **
dtj_get_argv(JNIEnv * jenv,jobjectArray args,int * argc)10931449Stomee dtj_get_argv(JNIEnv *jenv, jobjectArray args, int *argc)
10941449Stomee {
10951449Stomee char **argv = NULL; /* return value */
10961449Stomee const char *str;
10971449Stomee int i;
10981449Stomee
10991449Stomee jstring jstr = NULL;
11001449Stomee
11011449Stomee if (!g_dtj_load_common) {
11021449Stomee dtj_throw_illegal_state(jenv,
11031449Stomee "dtj_load_common() has not been called");
11041449Stomee return (NULL);
11051449Stomee }
11061449Stomee
11071449Stomee *argc = (*jenv)->GetArrayLength(jenv, args);
11081449Stomee /*
11091449Stomee * Initialize all string pointers to NULL so that in case of an error
11101449Stomee * filling in the array, free_argv() will not attempt to free the
11111449Stomee * unallocated elements. Also NULL-terminate the string array for
11121449Stomee * functions that expect terminating NULL rather than rely on argc.
11131449Stomee */
11141449Stomee argv = uu_zalloc((sizeof (char *)) * (*argc + 1));
11151449Stomee if (!argv) {
11161449Stomee dtj_throw_out_of_memory(jenv, "Failed to allocate args array");
11171449Stomee return (NULL);
11181449Stomee }
11191449Stomee
11201449Stomee for (i = 0; i < *argc; ++i) {
11211449Stomee jstr = (*jenv)->GetObjectArrayElement(jenv, args, i);
11221449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
11231449Stomee dtj_free_argv(argv);
11241449Stomee return (NULL);
11251449Stomee }
11261449Stomee str = dtj_GetStringNativeChars(jenv, jstr);
11271449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
11281449Stomee dtj_free_argv(argv);
11291449Stomee (*jenv)->DeleteLocalRef(jenv, jstr);
11301449Stomee return (NULL);
11311449Stomee }
11321449Stomee argv[i] = malloc(strlen(str) + 1);
11331449Stomee if (!argv[i]) {
11341449Stomee dtj_throw_out_of_memory(jenv, "Failed to allocate arg");
11351449Stomee dtj_free_argv(argv);
11361449Stomee dtj_ReleaseStringNativeChars(jenv, jstr, str);
11371449Stomee (*jenv)->DeleteLocalRef(jenv, jstr);
11381449Stomee return (NULL);
11391449Stomee }
11401449Stomee (void) strcpy(argv[i], str);
11411449Stomee dtj_ReleaseStringNativeChars(jenv, jstr, str);
11421449Stomee (*jenv)->DeleteLocalRef(jenv, jstr);
11431449Stomee jstr = NULL;
11441449Stomee }
11451449Stomee
11461449Stomee return (argv);
11471449Stomee }
11481449Stomee
11491449Stomee char **
dtj_make_argv(JNIEnv * jenv,jstring command,int * argc)11501449Stomee dtj_make_argv(JNIEnv *jenv, jstring command, int *argc)
11511449Stomee {
11521449Stomee const char *ws = "\f\n\r\t\v ";
11531449Stomee char **argv = NULL; /* return value */
11541449Stomee const char *cmd; /* native command string */
11551449Stomee char *s; /* writable command */
11561449Stomee char *tok; /* token */
11571449Stomee int len;
11581449Stomee
11591449Stomee if (!g_dtj_load_common) {
11601449Stomee dtj_throw_illegal_state(jenv,
11611449Stomee "dtj_load_common() has not been called");
11621449Stomee return (NULL);
11631449Stomee }
11641449Stomee
11651449Stomee if (!command) {
11661449Stomee dtj_throw_null_pointer(jenv, "command is null");
11671449Stomee return (NULL);
11681449Stomee } else if ((*jenv)->GetStringLength(jenv, command) == 0) {
11691449Stomee dtj_throw_illegal_argument(jenv, "command is empty");
11701449Stomee return (NULL);
11711449Stomee }
11721449Stomee
11731449Stomee cmd = dtj_GetStringNativeChars(jenv, command);
11741449Stomee if ((*jenv)->ExceptionCheck(jenv)) {
11751449Stomee return (NULL);
11761449Stomee }
11771449Stomee len = strlen(cmd);
11781449Stomee s = malloc(len + 1);
11791449Stomee if (!s) {
11801449Stomee dtj_throw_out_of_memory(jenv,
11811449Stomee "failed to allocate command string");
11821449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd);
11831449Stomee return (NULL);
11841449Stomee }
11851449Stomee (void) strcpy(s, cmd);
11861449Stomee /*
11871449Stomee * Initialize all string pointers to NULL so that in case of an error
11881449Stomee * filling in the array, free_argv() will not attempt to free the
11891449Stomee * unallocated elements. Also NULL-terminate the string array for
11901449Stomee * functions that expect terminating NULL rather than rely on argc.
11911449Stomee * Allow for maximum length resulting from single-character tokens
11921449Stomee * separated by single spaces.
11931449Stomee */
11941449Stomee argv = uu_zalloc(sizeof (char *) * (len / 2 + 1));
11951449Stomee if (!argv) {
11961449Stomee dtj_throw_out_of_memory(jenv, "failed to allocate args array");
11971449Stomee free(s);
11981449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd);
11991449Stomee return (NULL);
12001449Stomee }
12011449Stomee
12021449Stomee *argc = 0;
12031449Stomee for (tok = strtok(s, ws); tok != NULL; tok = strtok(NULL, ws)) {
12041449Stomee argv[*argc] = malloc(strlen(tok) + 1);
12051449Stomee if (!argv[*argc]) {
12061449Stomee dtj_throw_out_of_memory(jenv, "Failed to allocate arg");
12071449Stomee dtj_free_argv(argv);
12081449Stomee free(s);
12091449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd);
12101449Stomee return (NULL);
12111449Stomee }
12121449Stomee (void) strcpy(argv[(*argc)++], tok);
12131449Stomee }
12141449Stomee
12151449Stomee if (*argc == 0) {
12161449Stomee dtj_throw_illegal_argument(jenv, "command is blank");
12171449Stomee dtj_free_argv(argv);
12181449Stomee free(s);
12191449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd);
12201449Stomee return (NULL);
12211449Stomee }
12221449Stomee
12231449Stomee free(s);
12241449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd);
12251449Stomee return (argv);
12261449Stomee }
12271449Stomee
12281449Stomee void
dtj_free_argv(char ** argv)12291449Stomee dtj_free_argv(char **argv)
12301449Stomee {
12311449Stomee if (argv) {
12321449Stomee char **s = argv;
12331449Stomee while (*s) {
12341449Stomee free((void *)*s);
12351449Stomee *s++ = NULL;
12361449Stomee }
12371449Stomee free((void *)argv);
12381449Stomee }
12391449Stomee }
12401449Stomee
12411449Stomee
12421449Stomee /* Wrappers for uu_list_t */
12431449Stomee
12441449Stomee int
12451449Stomee /* ARGSUSED */
dtj_pointer_list_entry_cmp(const void * v1,const void * v2,void * arg)12461449Stomee dtj_pointer_list_entry_cmp(const void *v1, const void *v2, void *arg)
12471449Stomee {
12481449Stomee const dtj_pointer_list_entry_t *p1 = v1;
12491449Stomee const dtj_pointer_list_entry_t *p2 = v2;
12501449Stomee
12511449Stomee /*
12521449Stomee * It is not valid to compare pointers using the relational operators
12531449Stomee * unless they point to elements in the same array.
12541449Stomee */
12551717Swesolows uint64_t x = (uintptr_t)p1->dple_ptr;
12561717Swesolows uint64_t y = (uintptr_t)p2->dple_ptr;
12571449Stomee int rc;
12581449Stomee rc = ((x > y) ? 1 : ((x < y) ? -1 : 0));
12591449Stomee return (rc);
12601449Stomee }
12611449Stomee
12621449Stomee int
12631449Stomee /* ARGSUSED */
dtj_string_list_entry_cmp(const void * v1,const void * v2,void * arg)12641449Stomee dtj_string_list_entry_cmp(const void *v1, const void *v2, void *arg)
12651449Stomee {
12661449Stomee const dtj_string_list_entry_t *p1 = v1;
12671449Stomee const dtj_string_list_entry_t *p2 = v2;
12681449Stomee const char *s1 = p1->dsle_value;
12691449Stomee const char *s2 = p2->dsle_value;
12701449Stomee if (s1 == NULL) {
12711449Stomee return (s2 == NULL ? 0 : -1);
12721449Stomee }
12731449Stomee if (s2 == NULL) {
12741449Stomee return (1);
12751449Stomee }
12761449Stomee return (strcmp(s1, s2));
12771449Stomee }
12781449Stomee
12791449Stomee static boolean_t
dtj_check_pointer_pool(void)12801449Stomee dtj_check_pointer_pool(void)
12811449Stomee {
12821449Stomee if (g_pointer_pool == NULL) {
12831449Stomee g_pointer_pool = uu_list_pool_create("g_pointer_pool",
12841449Stomee sizeof (dtj_pointer_list_entry_t),
12851449Stomee offsetof(dtj_pointer_list_entry_t, dple_node),
12861449Stomee dtj_pointer_list_entry_cmp,
12871449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
12881449Stomee if (g_pointer_pool == NULL) {
12891449Stomee return (B_FALSE);
12901449Stomee }
12911449Stomee }
12921449Stomee return (B_TRUE);
12931449Stomee }
12941449Stomee
12951449Stomee uu_list_t *
dtj_pointer_list_create(void)12961449Stomee dtj_pointer_list_create(void)
12971449Stomee {
12981449Stomee uu_list_t *list;
12991449Stomee
13001449Stomee if (!dtj_check_pointer_pool()) {
13011449Stomee return (NULL);
13021449Stomee }
13031449Stomee
13041449Stomee list = uu_list_create(g_pointer_pool, NULL,
13051449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
13061449Stomee return (list);
13071449Stomee }
13081449Stomee
13091449Stomee dtj_pointer_list_entry_t *
dtj_pointer_list_entry_create(void * p)13101449Stomee dtj_pointer_list_entry_create(void *p)
13111449Stomee {
13121449Stomee dtj_pointer_list_entry_t *e;
13131449Stomee
13141449Stomee if (!dtj_check_pointer_pool()) {
13151449Stomee return (NULL);
13161449Stomee }
13171449Stomee
13181449Stomee e = uu_zalloc(sizeof (dtj_pointer_list_entry_t));
13191449Stomee if (e) {
13201449Stomee uu_list_node_init(e, &e->dple_node, g_pointer_pool);
13211449Stomee e->dple_ptr = p;
13221449Stomee }
13231449Stomee return (e);
13241449Stomee }
13251449Stomee
13261449Stomee static boolean_t
dtj_check_string_pool(void)13271449Stomee dtj_check_string_pool(void)
13281449Stomee {
13291449Stomee if (g_string_pool == NULL) {
13301449Stomee g_string_pool = uu_list_pool_create("g_string_pool",
13311449Stomee sizeof (dtj_string_list_entry_t),
13321449Stomee offsetof(dtj_string_list_entry_t, dsle_node),
13331449Stomee dtj_string_list_entry_cmp,
13341449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
13351449Stomee if (g_string_pool == NULL) {
13361449Stomee return (B_FALSE);
13371449Stomee }
13381449Stomee }
13391449Stomee return (B_TRUE);
13401449Stomee }
13411449Stomee
13421449Stomee uu_list_t *
dtj_string_list_create(void)13431449Stomee dtj_string_list_create(void)
13441449Stomee {
13451449Stomee uu_list_t *list;
13461449Stomee
13471449Stomee if (!dtj_check_string_pool()) {
13481449Stomee return (NULL);
13491449Stomee }
13501449Stomee
13511449Stomee list = uu_list_create(g_string_pool, NULL,
13521449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0));
13531449Stomee return (list);
13541449Stomee }
13551449Stomee
13561449Stomee dtj_string_list_entry_t *
dtj_string_list_entry_create(const char * s)13571449Stomee dtj_string_list_entry_create(const char *s)
13581449Stomee {
13591449Stomee dtj_string_list_entry_t *e;
13601449Stomee
13611449Stomee if (!dtj_check_string_pool()) {
13621449Stomee return (NULL);
13631449Stomee }
13641449Stomee
13651449Stomee e = uu_zalloc(sizeof (dtj_string_list_entry_t));
13661449Stomee if (e) {
13671449Stomee uu_list_node_init(e, &e->dsle_node, g_string_pool);
13681449Stomee if (s) {
13691449Stomee e->dsle_value = malloc(strlen(s) + 1);
13701449Stomee if (e->dsle_value) {
13711449Stomee (void) strcpy(e->dsle_value, s);
13721449Stomee } else {
13731449Stomee uu_list_node_fini(e, &e->dsle_node,
13741449Stomee g_string_pool);
13751449Stomee uu_free(e);
13761449Stomee e = NULL;
13771449Stomee }
13781449Stomee }
13791449Stomee }
13801449Stomee return (e);
13811449Stomee }
13821449Stomee
13831449Stomee void
dtj_pointer_list_entry_destroy(void * v,dtj_value_destroy_f * value_destroy,void * arg)13841449Stomee dtj_pointer_list_entry_destroy(void *v,
13851449Stomee dtj_value_destroy_f *value_destroy, void *arg)
13861449Stomee {
13871449Stomee if (v) {
13881449Stomee dtj_pointer_list_entry_t *e = v;
13891449Stomee if (value_destroy) {
13901449Stomee value_destroy(e->dple_ptr, arg);
13911449Stomee }
13921449Stomee uu_list_node_fini(e, &e->dple_node, g_pointer_pool);
13931449Stomee e->dple_ptr = NULL;
13941449Stomee uu_free(v);
13951449Stomee }
13961449Stomee }
13971449Stomee
13981449Stomee void
13991449Stomee /* ARGSUSED */
dtj_string_list_entry_destroy(void * v,void * arg)14001449Stomee dtj_string_list_entry_destroy(void *v, void *arg)
14011449Stomee {
14021449Stomee if (v) {
14031449Stomee dtj_string_list_entry_t *e = v;
14041449Stomee free(e->dsle_value);
14051449Stomee uu_list_node_fini(e, &e->dsle_node, g_string_pool);
14061449Stomee e->dsle_value = NULL;
14071449Stomee uu_free(v);
14081449Stomee }
14091449Stomee }
14101449Stomee
14111449Stomee void
dtj_list_clear(uu_list_t * list,dtj_value_destroy_f * value_destroy,void * arg)14121449Stomee dtj_list_clear(uu_list_t *list, dtj_value_destroy_f *value_destroy,
14131449Stomee void *arg)
14141449Stomee {
14151449Stomee void *cookie; /* needed for uu_list_teardown */
14161449Stomee void *value;
14171449Stomee
14181449Stomee if (!list) {
14191449Stomee return;
14201449Stomee }
14211449Stomee
14221449Stomee cookie = NULL;
14231449Stomee if (value_destroy) {
14241449Stomee while ((value = uu_list_teardown(list, &cookie)) != NULL) {
14251449Stomee value_destroy(value, arg);
14261449Stomee }
14271449Stomee } else {
14281449Stomee while ((value = uu_list_teardown(list, &cookie)) != NULL) {
14291449Stomee }
14301449Stomee }
14311449Stomee }
14321449Stomee
14331449Stomee void
dtj_list_destroy(uu_list_t * list,dtj_value_destroy_f * value_destroy,void * arg)14341449Stomee dtj_list_destroy(uu_list_t *list,
14351449Stomee dtj_value_destroy_f *value_destroy, void *arg)
14361449Stomee {
14371449Stomee dtj_list_clear(list, value_destroy, arg);
14381449Stomee uu_list_destroy(list);
14391449Stomee }
14401449Stomee
14411449Stomee void
dtj_pointer_list_clear(uu_list_t * list,dtj_value_destroy_f * value_destroy,void * arg)14421449Stomee dtj_pointer_list_clear(uu_list_t *list,
14431449Stomee dtj_value_destroy_f *value_destroy, void *arg)
14441449Stomee {
14451449Stomee void *cookie; /* needed for uu_list_teardown */
14461449Stomee dtj_pointer_list_entry_t *e;
14471449Stomee
14481449Stomee if (!list) {
14491449Stomee return;
14501449Stomee }
14511449Stomee
14521449Stomee cookie = NULL;
14531449Stomee while ((e = uu_list_teardown(list, &cookie)) != NULL) {
14541449Stomee dtj_pointer_list_entry_destroy(e, value_destroy, arg);
14551449Stomee }
14561449Stomee }
14571449Stomee
14581449Stomee void
dtj_pointer_list_destroy(uu_list_t * list,dtj_value_destroy_f * value_destroy,void * arg)14591449Stomee dtj_pointer_list_destroy(uu_list_t *list,
14601449Stomee dtj_value_destroy_f *value_destroy, void *arg)
14611449Stomee {
14621449Stomee dtj_pointer_list_clear(list, value_destroy, arg);
14631449Stomee uu_list_destroy(list);
14641449Stomee }
14651449Stomee
14661449Stomee void
dtj_string_list_clear(uu_list_t * list)14671449Stomee dtj_string_list_clear(uu_list_t *list)
14681449Stomee {
14691449Stomee dtj_list_clear(list, dtj_string_list_entry_destroy, NULL);
14701449Stomee }
14711449Stomee
14721449Stomee void
dtj_string_list_destroy(uu_list_t * list)14731449Stomee dtj_string_list_destroy(uu_list_t *list)
14741449Stomee {
14751449Stomee dtj_list_destroy(list, dtj_string_list_entry_destroy, NULL);
14761449Stomee }
14771449Stomee
14781449Stomee boolean_t
dtj_list_empty(uu_list_t * list)14791449Stomee dtj_list_empty(uu_list_t *list)
14801449Stomee {
14811449Stomee return (uu_list_numnodes(list) == 0);
14821449Stomee }
14831449Stomee
14841449Stomee boolean_t
dtj_list_add(uu_list_t * list,void * value)14851449Stomee dtj_list_add(uu_list_t *list, void *value)
14861449Stomee {
14871449Stomee return (uu_list_insert_before(list, NULL, value) == 0);
14881449Stomee }
14891449Stomee
14901449Stomee boolean_t
dtj_pointer_list_add(uu_list_t * list,void * p)14911449Stomee dtj_pointer_list_add(uu_list_t *list, void *p)
14921449Stomee {
14931449Stomee dtj_pointer_list_entry_t *e = dtj_pointer_list_entry_create(p);
14941449Stomee if (!e) {
14951449Stomee return (B_FALSE);
14961449Stomee }
14971449Stomee return (dtj_list_add(list, e));
14981449Stomee }
14991449Stomee
15001449Stomee void *
dtj_pointer_list_walk_next(uu_list_walk_t * itr)15011449Stomee dtj_pointer_list_walk_next(uu_list_walk_t *itr)
15021449Stomee {
15031449Stomee dtj_pointer_list_entry_t *e = uu_list_walk_next(itr);
15041449Stomee if (!e) {
15051449Stomee return (DTJ_INVALID_PTR);
15061449Stomee }
15071449Stomee return (e->dple_ptr);
15081449Stomee }
15091449Stomee
15101449Stomee void *
dtj_pointer_list_first(uu_list_t * list)15111449Stomee dtj_pointer_list_first(uu_list_t *list)
15121449Stomee {
15131449Stomee dtj_pointer_list_entry_t *e = uu_list_first(list);
15141449Stomee if (!e) {
15151449Stomee /* NULL is a valid value; use -1 for invalid */
15161449Stomee return (DTJ_INVALID_PTR);
15171449Stomee }
15181449Stomee return (e->dple_ptr);
15191449Stomee }
15201449Stomee
15211449Stomee void *
dtj_pointer_list_last(uu_list_t * list)15221449Stomee dtj_pointer_list_last(uu_list_t *list)
15231449Stomee {
15241449Stomee dtj_pointer_list_entry_t *e = uu_list_last(list);
15251449Stomee if (!e) {
15261449Stomee /* NULL is a valid value; use -1 for invalid */
15271449Stomee return (DTJ_INVALID_PTR);
15281449Stomee }
15291449Stomee return (e->dple_ptr);
15301449Stomee }
15311449Stomee
15321449Stomee boolean_t
dtj_string_list_add(uu_list_t * list,const char * s)15331449Stomee dtj_string_list_add(uu_list_t *list, const char *s)
15341449Stomee {
15351449Stomee dtj_string_list_entry_t *e = dtj_string_list_entry_create(s);
15361449Stomee if (!e) {
15371449Stomee return (B_FALSE);
15381449Stomee }
15391449Stomee return (dtj_list_add(list, e));
15401449Stomee }
15411449Stomee
15421449Stomee const char *
dtj_string_list_walk_next(uu_list_walk_t * itr)15431449Stomee dtj_string_list_walk_next(uu_list_walk_t *itr)
15441449Stomee {
15451449Stomee dtj_string_list_entry_t *e = uu_list_walk_next(itr);
15461449Stomee if (!e) {
15471449Stomee return (DTJ_INVALID_STR);
15481449Stomee }
15491449Stomee return (e->dsle_value);
15501449Stomee }
15511449Stomee
15521449Stomee const char *
dtj_string_list_first(uu_list_t * list)15531449Stomee dtj_string_list_first(uu_list_t *list)
15541449Stomee {
15551449Stomee dtj_string_list_entry_t *e = uu_list_first(list);
15561449Stomee if (!e) {
15571449Stomee /* NULL is a valid string value; use -1 for invalid */
15581449Stomee return (DTJ_INVALID_STR);
15591449Stomee }
15601449Stomee return (e->dsle_value);
15611449Stomee }
15621449Stomee
15631449Stomee const char *
dtj_string_list_last(uu_list_t * list)15641449Stomee dtj_string_list_last(uu_list_t *list)
15651449Stomee {
15661449Stomee dtj_string_list_entry_t *e = uu_list_last(list);
15671449Stomee if (!e) {
15681449Stomee /* NULL is a valid string value; use -1 for invalid */
15691449Stomee return (DTJ_INVALID_STR);
15701449Stomee }
15711449Stomee return (e->dsle_value);
15721449Stomee }
1573