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 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 */ 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 */ 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 */ 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 * 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 * 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 * 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 * 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 * 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 */ 1087fb3fb4f3Stomee dtj_ReleaseStringNativeChars(JNIEnv *jenv, jstring jstr, const char *str) 1088fb3fb4f3Stomee { 1089fb3fb4f3Stomee free((void *)str); 1090fb3fb4f3Stomee } 1091fb3fb4f3Stomee 1092fb3fb4f3Stomee char ** 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 ** 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 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 */ 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 */ 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 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 * 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 * 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 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 * 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 * 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 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 */ 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 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 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 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 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 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 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 1479fb3fb4f3Stomee dtj_list_empty(uu_list_t *list) 1480fb3fb4f3Stomee { 1481fb3fb4f3Stomee return (uu_list_numnodes(list) == 0); 1482fb3fb4f3Stomee } 1483fb3fb4f3Stomee 1484fb3fb4f3Stomee boolean_t 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 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 * 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 * 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 * 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 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 * 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 * 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 * 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