Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improvements to new lib loader. Now also can handle a list of libs taken ie. from an env var. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
492ee97daf38a817810b655bd60c8469 |
User & Date: | stu 2017-05-27 11:59:54 |
Context
2017-05-29
| ||
04:57 | Fix inverted test in new loader. check-in: 986133b362 user: stu tags: trunk | |
2017-05-27
| ||
11:59 | Improvements to new lib loader. Now also can handle a list of libs taken ie. from an env var. check-in: 492ee97daf user: stu tags: trunk | |
2017-05-26
| ||
23:17 | Trying out a new lib loader, currently disabled. Hoping to bring this to the other TDBC-* drivers; their loaders could be more consistent with each other. Looking for feedback. check-in: 529b2be8a7 user: stu tags: trunk | |
Changes
Changes to generic/odbcStubInit.c.
︙ | ︙ | |||
27 28 29 30 31 32 33 | /* * Names of the libraries that might contain the ODBC API */ /* Uncomment or -DTDBC_NEW_LOADER=1 to use the new loader */ | | > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /* * Names of the libraries that might contain the ODBC API */ /* Uncomment or -DTDBC_NEW_LOADER=1 to use the new loader */ /*#define TDBC_NEW_LOADER 1*/ #ifdef TDBC_NEW_LOADER #include <stdlib.h> /* Sorted by name asc. */ static const char *const odbcStubLibNames[] = { "iodbc", "odbc", "odbc32", NULL }; /* Sorted by num desc. No leading dots. Empty first. */ static const char *const odbcStubLibNumbers[] = { |
︙ | ︙ | |||
154 155 156 157 158 159 160 | }; /* *----------------------------------------------------------------------------- * * tdbcLoadLib -- * | | | | | | | | > | > > | | | > > > > > > > > > > > | | > > | > > > > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > > | | | | | < | < < > | < | > | > | < > | | > | | | | | > | | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | }; /* *----------------------------------------------------------------------------- * * tdbcLoadLib -- * * Tries to load a shared library given a list of lib names and/or * all combinations of LIBPREFIX, no LIBPREFIX, lib names and lib numbers. * Takes CYGWIN into account. * * Results: * Returns the handle to the loaded ODBC client library and leaves the * name of the the loaded ODBC client library in the interpreter, or NULL * if the load is unsuccessful and leaves a list of error message(s) in the * interpreter. * *----------------------------------------------------------------------------- */ static Tcl_LoadHandle tdbcLoadLib ( Tcl_Interp *interp, /* Receives errors or lib name if successful */ const char *const soNames[], /* Lib names. Kwazy lookup not done if NULL */ const char *const soNumbers[], /* Lib numbers for kwazy lookup */ const char *const soSymbolNames[], /* Passed to Tcl_LoadFile */ const void *soStubDefs, /* Passed to Tcl_LoadFile */ const char *soList, /* Lib name list to try first if not NULL */ const char *const soFormats[] /* Lib name printf formats for kwazy lookup. Default used if NULL. Maybe not useful as a parameter. */ ) { const char *const *nam; /* Name */ const char *const *num; /* Number */ const char *const *fmt; /* Format */ Tcl_Obj *lib; /* Holds lib name during kwazy lookup */ Tcl_Obj *result; /* List of errors or lib name if successful */ Tcl_LoadHandle handle; /* NULL or handle to loaded lib if successful */ result = NULL; /* Important! This is eventually returned. */ handle = NULL; /* Important! This is eventually returned. */ /* * Try to load a lib from a string claiming to be a list of libs? */ if (soList != NULL) { /* Yes! */ Tcl_Obj *l; Tcl_Obj **els; int nels; int i; /* * Make list from string. * Caller is responsible for listability and utf8ness. */ l = Tcl_NewStringObj(soList, -1); Tcl_IncrRefCount(l); if (Tcl_ListObjGetElements(interp, l, &nels, &els) != TCL_OK) { Tcl_DecrRefCount(l); return NULL; } result = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(result); /* * Left-to-right, trying to load a lib at each iteration. */ for (i = 0; i < nels; i++) { if (Tcl_LoadFile(interp, els[i], soSymbolNames, 0, (void *) soStubDefs, &handle) == TCL_OK) { /* Lib found and loaded. Cleanup and setup result. */ Tcl_DecrRefCount(result); /* Throw away any accumulated errors. */ result = Tcl_DuplicateObj(els[i]); Tcl_IncrRefCount(result); break; } Tcl_ListObjAppendElement(NULL, result, Tcl_GetObjResult(interp)); /* Collect error. */ handle = NULL; /* Important! This is eventually returned. */ } Tcl_DecrRefCount(l); if (handle != NULL) { goto loadDone; } } /* * At this point no lib list was provided or no lib was found in the list. */ /* * Done if names not provided. */ if (soNames == NULL) { goto loadDone; } /* * Use default format(s) if not supplied. */ if (soFormats == NULL) { soFormats = tdbcLibFormats; } if (result != NULL) { result = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(result); } /* * Try every possible combination (aka Kwazy Lookup). */ for (nam = &soNames[0]; *nam != NULL; nam++) { for (num = &soNumbers[0]; *num != NULL; num++) { for (fmt = &soFormats[0]; *fmt != NULL; fmt++) { lib = Tcl_ObjPrintf(*fmt, *nam, (*num[0] == '\0' ? "" : TDBC_SHLIB_SEP), *num); Tcl_IncrRefCount(lib); if (Tcl_LoadFile(interp, lib, soSymbolNames, 0, (void *) soStubDefs, &handle) == TCL_OK) { /* Lib found and loaded. Cleanup and setup result. */ Tcl_DecrRefCount(result); /* Throw away any accumulated errors. */ result = lib; goto loadDone; } Tcl_ListObjAppendElement(NULL, result, Tcl_GetObjResult(interp)); /* Collect error. */ Tcl_DecrRefCount(lib); handle = NULL; /* Important! This is eventually returned. */ }}} loadDone: if (result != NULL) { Tcl_SetObjResult(interp, result); Tcl_DecrRefCount(result); } return handle; /* Like I said... */ } /* *----------------------------------------------------------------------------- * * OdbcInitStubs -- * |
︙ | ︙ | |||
238 239 240 241 242 243 244 | MODULE_SCOPE Tcl_LoadHandle OdbcInitStubs(Tcl_Interp* interp, /* Tcl interpreter */ Tcl_LoadHandle* handle2Ptr) /* Pointer to a second load handle * that represents the ODBCINST library */ { | > | | < | | > > > > | | | | > > > > | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | MODULE_SCOPE Tcl_LoadHandle OdbcInitStubs(Tcl_Interp* interp, /* Tcl interpreter */ Tcl_LoadHandle* handle2Ptr) /* Pointer to a second load handle * that represents the ODBCINST library */ { Tcl_LoadHandle handle; /* Handle to a load module */ int status; /* Status of Tcl library calls for ODBC lib */ int status2; /* Status of Tcl library calls for ODBCINST lib */ SQLConfigDataSourceW = NULL;/* Symbols maybe in ODBCINST lib */ SQLConfigDataSource = NULL; SQLInstallerError = NULL; /* * Try to load a client library and resolve the ODBC API within it. */ handle = tdbcLoadLib(interp, odbcStubLibNames, odbcStubLibNumbers, odbcSymbolNames, odbcStubs, getenv("TDBC_ODBC_ODBCLIBS"), NULL ); status = (handle == NULL ? TCL_ERROR : TCL_OK); /* * We've run out of library names (in which case status==TCL_ERROR * and the error message reflects the last unsuccessful load attempt). */ if (status != TCL_OK) { return NULL; } /* * If a client library is found, then try to load ODBCINST as well. */ *handle2Ptr = tdbcLoadLib(interp, odbcOptLibNames, odbcOptLibNumbers, NULL, NULL, getenv("TDBC_ODBC_ODBCINSTLIBS"), NULL ); status2 = (*handle2Ptr == NULL ? TCL_ERROR : TCL_OK); if (status2 == TCL_OK) { SQLConfigDataSourceW = (BOOL (INSTAPI*)(HWND, WORD, LPCWSTR, LPCWSTR)) Tcl_FindSymbol(NULL, *handle2Ptr, "SQLConfigDataSourceW"); if (SQLConfigDataSourceW == NULL) { SQLConfigDataSource = (BOOL (INSTAPI*)(HWND, WORD, LPCSTR, LPCSTR)) Tcl_FindSymbol(NULL, *handle2Ptr, |
︙ | ︙ |