1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/common/icuplug.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,843 @@ 1.4 +/* 1.5 +****************************************************************************** 1.6 +* 1.7 +* Copyright (C) 2009-2012, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +****************************************************************************** 1.11 +* 1.12 +* FILE NAME : icuplug.c 1.13 +* 1.14 +* Date Name Description 1.15 +* 10/29/2009 sl New. 1.16 +****************************************************************************** 1.17 +*/ 1.18 + 1.19 +#include "unicode/icuplug.h" 1.20 +#include "icuplugimp.h" 1.21 +#include "cstring.h" 1.22 +#include "cmemory.h" 1.23 +#include "putilimp.h" 1.24 +#include "ucln.h" 1.25 +#include <stdio.h> 1.26 +#ifdef __MVS__ /* defined by z/OS compiler */ 1.27 +#define _POSIX_SOURCE 1.28 +#include <cics.h> /* 12 Nov 2011 JAM iscics() function */ 1.29 +#endif 1.30 + 1.31 +#ifndef UPLUG_TRACE 1.32 +#define UPLUG_TRACE 0 1.33 +#endif 1.34 + 1.35 +#if UPLUG_TRACE 1.36 +#include <stdio.h> 1.37 +#define DBG(x) fprintf(stderr, "%s:%d: ",__FILE__,__LINE__); fprintf x 1.38 +#endif 1.39 + 1.40 +/** 1.41 + * Internal structure of an ICU plugin. 1.42 + */ 1.43 + 1.44 +struct UPlugData { 1.45 + UPlugEntrypoint *entrypoint; /**< plugin entrypoint */ 1.46 + uint32_t structSize; /**< initialized to the size of this structure */ 1.47 + uint32_t token; /**< must be U_PLUG_TOKEN */ 1.48 + void *lib; /**< plugin library, or NULL */ 1.49 + char libName[UPLUG_NAME_MAX]; /**< library name */ 1.50 + char sym[UPLUG_NAME_MAX]; /**< plugin symbol, or NULL */ 1.51 + char config[UPLUG_NAME_MAX]; /**< configuration data */ 1.52 + void *context; /**< user context data */ 1.53 + char name[UPLUG_NAME_MAX]; /**< name of plugin */ 1.54 + UPlugLevel level; /**< level of plugin */ 1.55 + UBool awaitingLoad; /**< TRUE if the plugin is awaiting a load call */ 1.56 + UBool dontUnload; /**< TRUE if plugin must stay resident (leak plugin and lib) */ 1.57 + UErrorCode pluginStatus; /**< status code of plugin */ 1.58 +}; 1.59 + 1.60 + 1.61 + 1.62 +#define UPLUG_LIBRARY_INITIAL_COUNT 8 1.63 +#define UPLUG_PLUGIN_INITIAL_COUNT 12 1.64 + 1.65 +/** 1.66 + * Remove an item 1.67 + * @param list the full list 1.68 + * @param listSize the number of entries in the list 1.69 + * @param memberSize the size of one member 1.70 + * @param itemToRemove the item number of the member 1.71 + * @return the new listsize 1.72 + */ 1.73 +static int32_t uplug_removeEntryAt(void *list, int32_t listSize, int32_t memberSize, int32_t itemToRemove) { 1.74 + uint8_t *bytePtr = (uint8_t *)list; 1.75 + 1.76 + /* get rid of some bad cases first */ 1.77 + if(listSize<1) { 1.78 + return listSize; 1.79 + } 1.80 + 1.81 + /* is there anything to move? */ 1.82 + if(listSize > itemToRemove+1) { 1.83 + memmove(bytePtr+(itemToRemove*memberSize), bytePtr+((itemToRemove+1)*memberSize), memberSize); 1.84 + } 1.85 + 1.86 + return listSize-1; 1.87 +} 1.88 + 1.89 + 1.90 + 1.91 + 1.92 +#if U_ENABLE_DYLOAD 1.93 +/** 1.94 + * Library management. Internal. 1.95 + * @internal 1.96 + */ 1.97 +struct UPlugLibrary; 1.98 + 1.99 +/** 1.100 + * Library management. Internal. 1.101 + * @internal 1.102 + */ 1.103 +typedef struct UPlugLibrary { 1.104 + void *lib; /**< library ptr */ 1.105 + char name[UPLUG_NAME_MAX]; /**< library name */ 1.106 + uint32_t ref; /**< reference count */ 1.107 +} UPlugLibrary; 1.108 + 1.109 +static UPlugLibrary staticLibraryList[UPLUG_LIBRARY_INITIAL_COUNT]; 1.110 +static UPlugLibrary * libraryList = staticLibraryList; 1.111 +static int32_t libraryCount = 0; 1.112 +static int32_t libraryMax = UPLUG_LIBRARY_INITIAL_COUNT; 1.113 + 1.114 +/** 1.115 + * Search for a library. Doesn't lock 1.116 + * @param libName libname to search for 1.117 + * @return the library's struct 1.118 + */ 1.119 +static int32_t searchForLibraryName(const char *libName) { 1.120 + int32_t i; 1.121 + 1.122 + for(i=0;i<libraryCount;i++) { 1.123 + if(!uprv_strcmp(libName, libraryList[i].name)) { 1.124 + return i; 1.125 + } 1.126 + } 1.127 + return -1; 1.128 +} 1.129 + 1.130 +static int32_t searchForLibrary(void *lib) { 1.131 + int32_t i; 1.132 + 1.133 + for(i=0;i<libraryCount;i++) { 1.134 + if(lib==libraryList[i].lib) { 1.135 + return i; 1.136 + } 1.137 + } 1.138 + return -1; 1.139 +} 1.140 + 1.141 +U_INTERNAL char * U_EXPORT2 1.142 +uplug_findLibrary(void *lib, UErrorCode *status) { 1.143 + int32_t libEnt; 1.144 + char *ret = NULL; 1.145 + if(U_FAILURE(*status)) { 1.146 + return NULL; 1.147 + } 1.148 + libEnt = searchForLibrary(lib); 1.149 + if(libEnt!=-1) { 1.150 + ret = libraryList[libEnt].name; 1.151 + } else { 1.152 + *status = U_MISSING_RESOURCE_ERROR; 1.153 + } 1.154 + return ret; 1.155 +} 1.156 + 1.157 +U_INTERNAL void * U_EXPORT2 1.158 +uplug_openLibrary(const char *libName, UErrorCode *status) { 1.159 + int32_t libEntry = -1; 1.160 + void *lib = NULL; 1.161 + 1.162 + if(U_FAILURE(*status)) return NULL; 1.163 + 1.164 + libEntry = searchForLibraryName(libName); 1.165 + if(libEntry == -1) { 1.166 + libEntry = libraryCount++; 1.167 + if(libraryCount >= libraryMax) { 1.168 + /* Ran out of library slots. Statically allocated because we can't depend on allocating memory.. */ 1.169 + *status = U_MEMORY_ALLOCATION_ERROR; 1.170 +#if UPLUG_TRACE 1.171 + DBG((stderr, "uplug_openLibrary() - out of library slots (max %d)\n", libraryMax)); 1.172 +#endif 1.173 + return NULL; 1.174 + } 1.175 + /* Some operating systems don't want 1.176 + DL operations from multiple threads. */ 1.177 + libraryList[libEntry].lib = uprv_dl_open(libName, status); 1.178 +#if UPLUG_TRACE 1.179 + DBG((stderr, "uplug_openLibrary(%s,%s) libEntry %d, lib %p\n", libName, u_errorName(*status), libEntry, lib)); 1.180 +#endif 1.181 + 1.182 + if(libraryList[libEntry].lib == NULL || U_FAILURE(*status)) { 1.183 + /* cleanup. */ 1.184 + libraryList[libEntry].lib = NULL; /* failure with open */ 1.185 + libraryList[libEntry].name[0] = 0; 1.186 +#if UPLUG_TRACE 1.187 + DBG((stderr, "uplug_openLibrary(%s,%s) libEntry %d, lib %p\n", libName, u_errorName(*status), libEntry, lib)); 1.188 +#endif 1.189 + /* no need to free - just won't increase the count. */ 1.190 + libraryCount--; 1.191 + } else { /* is it still there? */ 1.192 + /* link it in */ 1.193 + uprv_strncpy(libraryList[libEntry].name,libName,UPLUG_NAME_MAX); 1.194 + libraryList[libEntry].ref=1; 1.195 + lib = libraryList[libEntry].lib; 1.196 + } 1.197 + 1.198 + } else { 1.199 + lib = libraryList[libEntry].lib; 1.200 + libraryList[libEntry].ref++; 1.201 + } 1.202 + return lib; 1.203 +} 1.204 + 1.205 +U_INTERNAL void U_EXPORT2 1.206 +uplug_closeLibrary(void *lib, UErrorCode *status) { 1.207 + int32_t i; 1.208 + 1.209 +#if UPLUG_TRACE 1.210 + DBG((stderr, "uplug_closeLibrary(%p,%s) list %p\n", lib, u_errorName(*status), (void*)libraryList)); 1.211 +#endif 1.212 + if(U_FAILURE(*status)) return; 1.213 + 1.214 + for(i=0;i<libraryCount;i++) { 1.215 + if(lib==libraryList[i].lib) { 1.216 + if(--(libraryList[i].ref) == 0) { 1.217 + uprv_dl_close(libraryList[i].lib, status); 1.218 + libraryCount = uplug_removeEntryAt(libraryList, libraryCount, sizeof(*libraryList), i); 1.219 + } 1.220 + return; 1.221 + } 1.222 + } 1.223 + *status = U_INTERNAL_PROGRAM_ERROR; /* could not find the entry! */ 1.224 +} 1.225 + 1.226 +#endif 1.227 + 1.228 +static UPlugData pluginList[UPLUG_PLUGIN_INITIAL_COUNT]; 1.229 +static int32_t pluginCount = 0; 1.230 + 1.231 + 1.232 + 1.233 + 1.234 +static int32_t uplug_pluginNumber(UPlugData* d) { 1.235 + UPlugData *pastPlug = &pluginList[pluginCount]; 1.236 + if(d<=pluginList) { 1.237 + return 0; 1.238 + } else if(d>=pastPlug) { 1.239 + return pluginCount; 1.240 + } else { 1.241 + return (d-pluginList)/sizeof(pluginList[0]); 1.242 + } 1.243 +} 1.244 + 1.245 + 1.246 +U_CAPI UPlugData * U_EXPORT2 1.247 +uplug_nextPlug(UPlugData *prior) { 1.248 + if(prior==NULL) { 1.249 + return pluginList; 1.250 + } else { 1.251 + UPlugData *nextPlug = &prior[1]; 1.252 + UPlugData *pastPlug = &pluginList[pluginCount]; 1.253 + 1.254 + if(nextPlug>=pastPlug) { 1.255 + return NULL; 1.256 + } else { 1.257 + return nextPlug; 1.258 + } 1.259 + } 1.260 +} 1.261 + 1.262 + 1.263 + 1.264 +/** 1.265 + * Call the plugin with some params 1.266 + */ 1.267 +static void uplug_callPlug(UPlugData *plug, UPlugReason reason, UErrorCode *status) { 1.268 + UPlugTokenReturn token; 1.269 + if(plug==NULL||U_FAILURE(*status)) { 1.270 + return; 1.271 + } 1.272 + token = (*(plug->entrypoint))(plug, reason, status); 1.273 + if(token!=UPLUG_TOKEN) { 1.274 + *status = U_INTERNAL_PROGRAM_ERROR; 1.275 + } 1.276 +} 1.277 + 1.278 + 1.279 +static void uplug_unloadPlug(UPlugData *plug, UErrorCode *status) { 1.280 + if(plug->awaitingLoad) { /* shouldn't happen. Plugin hasn'tbeen loaded yet.*/ 1.281 + *status = U_INTERNAL_PROGRAM_ERROR; 1.282 + return; 1.283 + } 1.284 + if(U_SUCCESS(plug->pluginStatus)) { 1.285 + /* Don't unload a plug which has a failing load status - means it didn't actually load. */ 1.286 + uplug_callPlug(plug, UPLUG_REASON_UNLOAD, status); 1.287 + } 1.288 +} 1.289 + 1.290 +static void uplug_queryPlug(UPlugData *plug, UErrorCode *status) { 1.291 + if(!plug->awaitingLoad || !(plug->level == UPLUG_LEVEL_UNKNOWN) ) { /* shouldn't happen. Plugin hasn'tbeen loaded yet.*/ 1.292 + *status = U_INTERNAL_PROGRAM_ERROR; 1.293 + return; 1.294 + } 1.295 + plug->level = UPLUG_LEVEL_INVALID; 1.296 + uplug_callPlug(plug, UPLUG_REASON_QUERY, status); 1.297 + if(U_SUCCESS(*status)) { 1.298 + if(plug->level == UPLUG_LEVEL_INVALID) { 1.299 + plug->pluginStatus = U_PLUGIN_DIDNT_SET_LEVEL; 1.300 + plug->awaitingLoad = FALSE; 1.301 + } 1.302 + } else { 1.303 + plug->pluginStatus = U_INTERNAL_PROGRAM_ERROR; 1.304 + plug->awaitingLoad = FALSE; 1.305 + } 1.306 +} 1.307 + 1.308 + 1.309 +static void uplug_loadPlug(UPlugData *plug, UErrorCode *status) { 1.310 + if(!plug->awaitingLoad || (plug->level < UPLUG_LEVEL_LOW) ) { /* shouldn't happen. Plugin hasn'tbeen loaded yet.*/ 1.311 + *status = U_INTERNAL_PROGRAM_ERROR; 1.312 + return; 1.313 + } 1.314 + uplug_callPlug(plug, UPLUG_REASON_LOAD, status); 1.315 + plug->awaitingLoad = FALSE; 1.316 + if(!U_SUCCESS(*status)) { 1.317 + plug->pluginStatus = U_INTERNAL_PROGRAM_ERROR; 1.318 + } 1.319 +} 1.320 + 1.321 +static UPlugData *uplug_allocateEmptyPlug(UErrorCode *status) 1.322 +{ 1.323 + UPlugData *plug = NULL; 1.324 + 1.325 + if(U_FAILURE(*status)) { 1.326 + return NULL; 1.327 + } 1.328 + 1.329 + if(pluginCount == UPLUG_PLUGIN_INITIAL_COUNT) { 1.330 + *status = U_MEMORY_ALLOCATION_ERROR; 1.331 + return NULL; 1.332 + } 1.333 + 1.334 + plug = &pluginList[pluginCount++]; 1.335 + 1.336 + plug->token = UPLUG_TOKEN; 1.337 + plug->structSize = sizeof(UPlugData); 1.338 + plug->name[0]=0; 1.339 + plug->level = UPLUG_LEVEL_UNKNOWN; /* initialize to null state */ 1.340 + plug->awaitingLoad = TRUE; 1.341 + plug->dontUnload = FALSE; 1.342 + plug->pluginStatus = U_ZERO_ERROR; 1.343 + plug->libName[0] = 0; 1.344 + plug->config[0]=0; 1.345 + plug->sym[0]=0; 1.346 + plug->lib=NULL; 1.347 + plug->entrypoint=NULL; 1.348 + 1.349 + 1.350 + return plug; 1.351 +} 1.352 + 1.353 +static UPlugData *uplug_allocatePlug(UPlugEntrypoint *entrypoint, const char *config, void *lib, const char *symName, 1.354 + UErrorCode *status) { 1.355 + UPlugData *plug; 1.356 + 1.357 + if(U_FAILURE(*status)) { 1.358 + return NULL; 1.359 + } 1.360 + 1.361 + plug = uplug_allocateEmptyPlug(status); 1.362 + if(config!=NULL) { 1.363 + uprv_strncpy(plug->config, config, UPLUG_NAME_MAX); 1.364 + } else { 1.365 + plug->config[0] = 0; 1.366 + } 1.367 + 1.368 + if(symName!=NULL) { 1.369 + uprv_strncpy(plug->sym, symName, UPLUG_NAME_MAX); 1.370 + } else { 1.371 + plug->sym[0] = 0; 1.372 + } 1.373 + 1.374 + plug->entrypoint = entrypoint; 1.375 + plug->lib = lib; 1.376 + uplug_queryPlug(plug, status); 1.377 + 1.378 + return plug; 1.379 +} 1.380 + 1.381 +static void uplug_deallocatePlug(UPlugData *plug, UErrorCode *status) { 1.382 + UErrorCode subStatus = U_ZERO_ERROR; 1.383 + if(!plug->dontUnload) { 1.384 +#if U_ENABLE_DYLOAD 1.385 + uplug_closeLibrary(plug->lib, &subStatus); 1.386 +#endif 1.387 + } 1.388 + plug->lib = NULL; 1.389 + if(U_SUCCESS(*status) && U_FAILURE(subStatus)) { 1.390 + *status = subStatus; 1.391 + } 1.392 + /* shift plugins up and decrement count. */ 1.393 + if(U_SUCCESS(*status)) { 1.394 + /* all ok- remove. */ 1.395 + pluginCount = uplug_removeEntryAt(pluginList, pluginCount, sizeof(plug[0]), uplug_pluginNumber(plug)); 1.396 + } else { 1.397 + /* not ok- leave as a message. */ 1.398 + plug->awaitingLoad=FALSE; 1.399 + plug->entrypoint=0; 1.400 + plug->dontUnload=TRUE; 1.401 + } 1.402 +} 1.403 + 1.404 +static void uplug_doUnloadPlug(UPlugData *plugToRemove, UErrorCode *status) { 1.405 + if(plugToRemove != NULL) { 1.406 + uplug_unloadPlug(plugToRemove, status); 1.407 + uplug_deallocatePlug(plugToRemove, status); 1.408 + } 1.409 +} 1.410 + 1.411 +U_CAPI void U_EXPORT2 1.412 +uplug_removePlug(UPlugData *plug, UErrorCode *status) { 1.413 + UPlugData *cursor = NULL; 1.414 + UPlugData *plugToRemove = NULL; 1.415 + if(U_FAILURE(*status)) return; 1.416 + 1.417 + for(cursor=pluginList;cursor!=NULL;) { 1.418 + if(cursor==plug) { 1.419 + plugToRemove = plug; 1.420 + cursor=NULL; 1.421 + } else { 1.422 + cursor = uplug_nextPlug(cursor); 1.423 + } 1.424 + } 1.425 + 1.426 + uplug_doUnloadPlug(plugToRemove, status); 1.427 +} 1.428 + 1.429 + 1.430 + 1.431 + 1.432 +U_CAPI void U_EXPORT2 1.433 +uplug_setPlugNoUnload(UPlugData *data, UBool dontUnload) 1.434 +{ 1.435 + data->dontUnload = dontUnload; 1.436 +} 1.437 + 1.438 + 1.439 +U_CAPI void U_EXPORT2 1.440 +uplug_setPlugLevel(UPlugData *data, UPlugLevel level) { 1.441 + data->level = level; 1.442 +} 1.443 + 1.444 + 1.445 +U_CAPI UPlugLevel U_EXPORT2 1.446 +uplug_getPlugLevel(UPlugData *data) { 1.447 + return data->level; 1.448 +} 1.449 + 1.450 + 1.451 +U_CAPI void U_EXPORT2 1.452 +uplug_setPlugName(UPlugData *data, const char *name) { 1.453 + uprv_strncpy(data->name, name, UPLUG_NAME_MAX); 1.454 +} 1.455 + 1.456 + 1.457 +U_CAPI const char * U_EXPORT2 1.458 +uplug_getPlugName(UPlugData *data) { 1.459 + return data->name; 1.460 +} 1.461 + 1.462 + 1.463 +U_CAPI const char * U_EXPORT2 1.464 +uplug_getSymbolName(UPlugData *data) { 1.465 + return data->sym; 1.466 +} 1.467 + 1.468 +U_CAPI const char * U_EXPORT2 1.469 +uplug_getLibraryName(UPlugData *data, UErrorCode *status) { 1.470 + if(data->libName[0]) { 1.471 + return data->libName; 1.472 + } else { 1.473 +#if U_ENABLE_DYLOAD 1.474 + return uplug_findLibrary(data->lib, status); 1.475 +#else 1.476 + return NULL; 1.477 +#endif 1.478 + } 1.479 +} 1.480 + 1.481 +U_CAPI void * U_EXPORT2 1.482 +uplug_getLibrary(UPlugData *data) { 1.483 + return data->lib; 1.484 +} 1.485 + 1.486 +U_CAPI void * U_EXPORT2 1.487 +uplug_getContext(UPlugData *data) { 1.488 + return data->context; 1.489 +} 1.490 + 1.491 + 1.492 +U_CAPI void U_EXPORT2 1.493 +uplug_setContext(UPlugData *data, void *context) { 1.494 + data->context = context; 1.495 +} 1.496 + 1.497 +U_CAPI const char* U_EXPORT2 1.498 +uplug_getConfiguration(UPlugData *data) { 1.499 + return data->config; 1.500 +} 1.501 + 1.502 +U_INTERNAL UPlugData* U_EXPORT2 1.503 +uplug_getPlugInternal(int32_t n) { 1.504 + if(n <0 || n >= pluginCount) { 1.505 + return NULL; 1.506 + } else { 1.507 + return &(pluginList[n]); 1.508 + } 1.509 +} 1.510 + 1.511 + 1.512 +U_CAPI UErrorCode U_EXPORT2 1.513 +uplug_getPlugLoadStatus(UPlugData *plug) { 1.514 + return plug->pluginStatus; 1.515 +} 1.516 + 1.517 + 1.518 + 1.519 + 1.520 +/** 1.521 + * Initialize a plugin fron an entrypoint and library - but don't load it. 1.522 + */ 1.523 +static UPlugData* uplug_initPlugFromEntrypointAndLibrary(UPlugEntrypoint *entrypoint, const char *config, void *lib, const char *sym, 1.524 + UErrorCode *status) { 1.525 + UPlugData *plug = NULL; 1.526 + 1.527 + plug = uplug_allocatePlug(entrypoint, config, lib, sym, status); 1.528 + 1.529 + if(U_SUCCESS(*status)) { 1.530 + return plug; 1.531 + } else { 1.532 + uplug_deallocatePlug(plug, status); 1.533 + return NULL; 1.534 + } 1.535 +} 1.536 + 1.537 +U_CAPI UPlugData* U_EXPORT2 1.538 +uplug_loadPlugFromEntrypoint(UPlugEntrypoint *entrypoint, const char *config, UErrorCode *status) { 1.539 + UPlugData* plug = uplug_initPlugFromEntrypointAndLibrary(entrypoint, config, NULL, NULL, status); 1.540 + uplug_loadPlug(plug, status); 1.541 + return plug; 1.542 +} 1.543 + 1.544 +#if U_ENABLE_DYLOAD 1.545 + 1.546 +static UPlugData* 1.547 +uplug_initErrorPlug(const char *libName, const char *sym, const char *config, const char *nameOrError, UErrorCode loadStatus, UErrorCode *status) 1.548 +{ 1.549 + UPlugData *plug = uplug_allocateEmptyPlug(status); 1.550 + if(U_FAILURE(*status)) return NULL; 1.551 + 1.552 + plug->pluginStatus = loadStatus; 1.553 + plug->awaitingLoad = FALSE; /* Won't load. */ 1.554 + plug->dontUnload = TRUE; /* cannot unload. */ 1.555 + 1.556 + if(sym!=NULL) { 1.557 + uprv_strncpy(plug->sym, sym, UPLUG_NAME_MAX); 1.558 + } 1.559 + 1.560 + if(libName!=NULL) { 1.561 + uprv_strncpy(plug->libName, libName, UPLUG_NAME_MAX); 1.562 + } 1.563 + 1.564 + if(nameOrError!=NULL) { 1.565 + uprv_strncpy(plug->name, nameOrError, UPLUG_NAME_MAX); 1.566 + } 1.567 + 1.568 + if(config!=NULL) { 1.569 + uprv_strncpy(plug->config, config, UPLUG_NAME_MAX); 1.570 + } 1.571 + 1.572 + return plug; 1.573 +} 1.574 + 1.575 +/** 1.576 + * Fetch a plugin from DLL, and then initialize it from a library- but don't load it. 1.577 + */ 1.578 +static UPlugData* 1.579 +uplug_initPlugFromLibrary(const char *libName, const char *sym, const char *config, UErrorCode *status) { 1.580 + void *lib = NULL; 1.581 + UPlugData *plug = NULL; 1.582 + if(U_FAILURE(*status)) { return NULL; } 1.583 + lib = uplug_openLibrary(libName, status); 1.584 + if(lib!=NULL && U_SUCCESS(*status)) { 1.585 + UPlugEntrypoint *entrypoint = NULL; 1.586 + entrypoint = (UPlugEntrypoint*)uprv_dlsym_func(lib, sym, status); 1.587 + 1.588 + if(entrypoint!=NULL&&U_SUCCESS(*status)) { 1.589 + plug = uplug_initPlugFromEntrypointAndLibrary(entrypoint, config, lib, sym, status); 1.590 + if(plug!=NULL&&U_SUCCESS(*status)) { 1.591 + plug->lib = lib; /* plug takes ownership of library */ 1.592 + lib = NULL; /* library is now owned by plugin. */ 1.593 + } 1.594 + } else { 1.595 + UErrorCode subStatus = U_ZERO_ERROR; 1.596 + plug = uplug_initErrorPlug(libName,sym,config,"ERROR: Could not load entrypoint",(lib==NULL)?U_MISSING_RESOURCE_ERROR:*status,&subStatus); 1.597 + } 1.598 + if(lib!=NULL) { /* still need to close the lib */ 1.599 + UErrorCode subStatus = U_ZERO_ERROR; 1.600 + uplug_closeLibrary(lib, &subStatus); /* don't care here */ 1.601 + } 1.602 + } else { 1.603 + UErrorCode subStatus = U_ZERO_ERROR; 1.604 + plug = uplug_initErrorPlug(libName,sym,config,"ERROR: could not load library",(lib==NULL)?U_MISSING_RESOURCE_ERROR:*status,&subStatus); 1.605 + } 1.606 + return plug; 1.607 +} 1.608 + 1.609 +U_CAPI UPlugData* U_EXPORT2 1.610 +uplug_loadPlugFromLibrary(const char *libName, const char *sym, const char *config, UErrorCode *status) { 1.611 + UPlugData *plug = NULL; 1.612 + if(U_FAILURE(*status)) { return NULL; } 1.613 + plug = uplug_initPlugFromLibrary(libName, sym, config, status); 1.614 + uplug_loadPlug(plug, status); 1.615 + 1.616 + return plug; 1.617 +} 1.618 + 1.619 +#endif 1.620 + 1.621 +U_CAPI UPlugLevel U_EXPORT2 uplug_getCurrentLevel() { 1.622 + if(cmemory_inUse()) { 1.623 + return UPLUG_LEVEL_HIGH; 1.624 + } else { 1.625 + return UPLUG_LEVEL_LOW; 1.626 + } 1.627 +} 1.628 + 1.629 +static UBool U_CALLCONV uplug_cleanup(void) 1.630 +{ 1.631 + int32_t i; 1.632 + 1.633 + UPlugData *pluginToRemove; 1.634 + /* cleanup plugs */ 1.635 + for(i=0;i<pluginCount;i++) { 1.636 + UErrorCode subStatus = U_ZERO_ERROR; 1.637 + pluginToRemove = &pluginList[i]; 1.638 + /* unload and deallocate */ 1.639 + uplug_doUnloadPlug(pluginToRemove, &subStatus); 1.640 + } 1.641 + /* close other held libs? */ 1.642 + return TRUE; 1.643 +} 1.644 + 1.645 +#if U_ENABLE_DYLOAD 1.646 + 1.647 +static void uplug_loadWaitingPlugs(UErrorCode *status) { 1.648 + int32_t i; 1.649 + UPlugLevel currentLevel = uplug_getCurrentLevel(); 1.650 + 1.651 + if(U_FAILURE(*status)) { 1.652 + return; 1.653 + } 1.654 +#if UPLUG_TRACE 1.655 + DBG((stderr, "uplug_loadWaitingPlugs() Level: %d\n", currentLevel)); 1.656 +#endif 1.657 + /* pass #1: low level plugs */ 1.658 + for(i=0;i<pluginCount;i++) { 1.659 + UErrorCode subStatus = U_ZERO_ERROR; 1.660 + UPlugData *pluginToLoad = &pluginList[i]; 1.661 + if(pluginToLoad->awaitingLoad) { 1.662 + if(pluginToLoad->level == UPLUG_LEVEL_LOW) { 1.663 + if(currentLevel > UPLUG_LEVEL_LOW) { 1.664 + pluginToLoad->pluginStatus = U_PLUGIN_TOO_HIGH; 1.665 + } else { 1.666 + UPlugLevel newLevel; 1.667 + uplug_loadPlug(pluginToLoad, &subStatus); 1.668 + newLevel = uplug_getCurrentLevel(); 1.669 + if(newLevel > currentLevel) { 1.670 + pluginToLoad->pluginStatus = U_PLUGIN_CHANGED_LEVEL_WARNING; 1.671 + currentLevel = newLevel; 1.672 + } 1.673 + } 1.674 + pluginToLoad->awaitingLoad = FALSE; 1.675 + } 1.676 + } 1.677 + } 1.678 + for(i=0;i<pluginCount;i++) { 1.679 + UErrorCode subStatus = U_ZERO_ERROR; 1.680 + UPlugData *pluginToLoad = &pluginList[i]; 1.681 + 1.682 + if(pluginToLoad->awaitingLoad) { 1.683 + if(pluginToLoad->level == UPLUG_LEVEL_INVALID) { 1.684 + pluginToLoad->pluginStatus = U_PLUGIN_DIDNT_SET_LEVEL; 1.685 + } else if(pluginToLoad->level == UPLUG_LEVEL_UNKNOWN) { 1.686 + pluginToLoad->pluginStatus = U_INTERNAL_PROGRAM_ERROR; 1.687 + } else { 1.688 + uplug_loadPlug(pluginToLoad, &subStatus); 1.689 + } 1.690 + pluginToLoad->awaitingLoad = FALSE; 1.691 + } 1.692 + } 1.693 + 1.694 +#if UPLUG_TRACE 1.695 + DBG((stderr, " Done Loading Plugs. Level: %d\n", (int32_t)uplug_getCurrentLevel())); 1.696 +#endif 1.697 +} 1.698 + 1.699 +/* Name of the plugin config file */ 1.700 +static char plugin_file[2048] = ""; 1.701 +#endif 1.702 + 1.703 +U_INTERNAL const char* U_EXPORT2 1.704 +uplug_getPluginFile() { 1.705 +#if U_ENABLE_DYLOAD 1.706 + return plugin_file; 1.707 +#else 1.708 + return NULL; 1.709 +#endif 1.710 +} 1.711 + 1.712 + 1.713 +U_CAPI void U_EXPORT2 1.714 +uplug_init(UErrorCode *status) { 1.715 +#if !U_ENABLE_DYLOAD 1.716 + (void)status; /* unused */ 1.717 +#else 1.718 + const char *plugin_dir; 1.719 + 1.720 + if(U_FAILURE(*status)) return; 1.721 + plugin_dir = getenv("ICU_PLUGINS"); 1.722 + 1.723 +#if defined(DEFAULT_ICU_PLUGINS) 1.724 + if(plugin_dir == NULL || !*plugin_dir) { 1.725 + plugin_dir = DEFAULT_ICU_PLUGINS; 1.726 + } 1.727 +#endif 1.728 + 1.729 +#if UPLUG_TRACE 1.730 + DBG((stderr, "ICU_PLUGINS=%s\n", plugin_dir)); 1.731 +#endif 1.732 + 1.733 + if(plugin_dir != NULL && *plugin_dir) { 1.734 + FILE *f; 1.735 + 1.736 + 1.737 +#ifdef OS390BATCH 1.738 +/* There are potentially a lot of ways to implement a plugin directory on OS390/zOS */ 1.739 +/* Keeping in mind that unauthorized file access is logged, monitored, and enforced */ 1.740 +/* I've chosen to open a DDNAME if BATCH and leave it alone for (presumably) UNIX */ 1.741 +/* System Services. Alternative techniques might be allocating a member in */ 1.742 +/* SYS1.PARMLIB or setting an environment variable "ICU_PLUGIN_PATH" (?). The */ 1.743 +/* DDNAME can be connected to a file in the HFS if need be. */ 1.744 + 1.745 + uprv_strncpy(plugin_file,"//DD:ICUPLUG", 2047); /* JAM 20 Oct 2011 */ 1.746 +#else 1.747 + uprv_strncpy(plugin_file, plugin_dir, 2047); 1.748 + uprv_strncat(plugin_file, U_FILE_SEP_STRING,2047); 1.749 + uprv_strncat(plugin_file, "icuplugins",2047); 1.750 + uprv_strncat(plugin_file, U_ICU_VERSION_SHORT ,2047); 1.751 + uprv_strncat(plugin_file, ".txt" ,2047); 1.752 +#endif 1.753 + 1.754 +#if UPLUG_TRACE 1.755 + DBG((stderr, "pluginfile= %s\n", plugin_file)); 1.756 +#endif 1.757 + 1.758 +#ifdef __MVS__ 1.759 + if (iscics()) /* 12 Nov 2011 JAM */ 1.760 + { 1.761 + f = NULL; 1.762 + } 1.763 + else 1.764 +#endif 1.765 + { 1.766 + f = fopen(plugin_file, "r"); 1.767 + } 1.768 + 1.769 + if(f != NULL) { 1.770 + char linebuf[1024]; 1.771 + char *p, *libName=NULL, *symName=NULL, *config=NULL; 1.772 + int32_t line = 0; 1.773 + 1.774 + 1.775 + while(fgets(linebuf,1023,f)) { 1.776 + line++; 1.777 + 1.778 + if(!*linebuf || *linebuf=='#') { 1.779 + continue; 1.780 + } else { 1.781 + p = linebuf; 1.782 + while(*p&&isspace((int)*p)) 1.783 + p++; 1.784 + if(!*p || *p=='#') continue; 1.785 + libName = p; 1.786 + while(*p&&!isspace((int)*p)) { 1.787 + p++; 1.788 + } 1.789 + if(!*p || *p=='#') continue; /* no tab after libname */ 1.790 + *p=0; /* end of libname */ 1.791 + p++; 1.792 + while(*p&&isspace((int)*p)) { 1.793 + p++; 1.794 + } 1.795 + if(!*p||*p=='#') continue; /* no symname after libname +tab */ 1.796 + symName = p; 1.797 + while(*p&&!isspace((int)*p)) { 1.798 + p++; 1.799 + } 1.800 + 1.801 + if(*p) { /* has config */ 1.802 + *p=0; 1.803 + ++p; 1.804 + while(*p&&isspace((int)*p)) { 1.805 + p++; 1.806 + } 1.807 + if(*p) { 1.808 + config = p; 1.809 + } 1.810 + } 1.811 + 1.812 + /* chop whitespace at the end of the config */ 1.813 + if(config!=NULL&&*config!=0) { 1.814 + p = config+strlen(config); 1.815 + while(p>config&&isspace((int)*(--p))) { 1.816 + *p=0; 1.817 + } 1.818 + } 1.819 + 1.820 + /* OK, we're good. */ 1.821 + { 1.822 + UErrorCode subStatus = U_ZERO_ERROR; 1.823 + UPlugData *plug = uplug_initPlugFromLibrary(libName, symName, config, &subStatus); 1.824 + if(U_FAILURE(subStatus) && U_SUCCESS(*status)) { 1.825 + *status = subStatus; 1.826 + } 1.827 +#if UPLUG_TRACE 1.828 + DBG((stderr, "PLUGIN libName=[%s], sym=[%s], config=[%s]\n", libName, symName, config)); 1.829 + DBG((stderr, " -> %p, %s\n", (void*)plug, u_errorName(subStatus))); 1.830 +#else 1.831 + (void)plug; /* unused */ 1.832 +#endif 1.833 + } 1.834 + } 1.835 + } 1.836 + fclose(f); 1.837 + } else { 1.838 +#if UPLUG_TRACE 1.839 + DBG((stderr, "Can't open plugin file %s\n", plugin_file)); 1.840 +#endif 1.841 + } 1.842 + } 1.843 + uplug_loadWaitingPlugs(status); 1.844 +#endif /* U_ENABLE_DYLOAD */ 1.845 + ucln_registerCleanup(UCLN_UPLUG, uplug_cleanup); 1.846 +}