blob: 832f02276efcc6e2927f340282a6e0f92fade15c [file] [log] [blame]
Guido van Rossum1ae940a1995-01-02 19:04:15 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum1ae940a1995-01-02 19:04:15 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Support for dynamic loading of extension modules */
26/* If no dynamic linking is supported, this file still generates some code! */
27
28#include "allobjects.h"
29#include "osdefs.h"
30#include "importdl.h"
31
Guido van Rossum1ae940a1995-01-02 19:04:15 +000032/* Explanation of some of the the various #defines used by dynamic linking...
33
34 symbol -- defined for:
35
36 DYNAMIC_LINK -- any kind of dynamic linking
Guido van Rossum75f288d1995-06-14 22:07:26 +000037 USE_RLD -- NeXT dynamic linking
Guido van Rossum1ae940a1995-01-02 19:04:15 +000038 USE_DL -- Jack's dl for IRIX 4 or GNU dld with emulation for Jack's dl
39 USE_SHLIB -- SunOS or IRIX 5 (SVR4?) shared libraries
40 _AIX -- AIX style dynamic linking
41 NT -- NT style dynamic linking (using DLLs)
Guido van Rossumdadc8241996-05-23 22:51:40 +000042 WIN16_DL -- Windows 16-bit dynamic linking (using DLLs)
Guido van Rossum1ae940a1995-01-02 19:04:15 +000043 _DL_FUNCPTR_DEFINED -- if the typedef dl_funcptr has been defined
Jack Jansen5d9acb61995-06-14 14:54:25 +000044 USE_MAC_DYNAMIC_LOADING -- Mac CFM shared libraries
Guido van Rossum1ae940a1995-01-02 19:04:15 +000045 SHORT_EXT -- short extension for dynamic module, e.g. ".so"
46 LONG_EXT -- long extension, e.g. "module.so"
47 hpux -- HP-UX Dynamic Linking - defined by the compiler
Guido van Rossum46c76a61995-01-20 16:53:54 +000048 __NetBSD__ -- NetBSD shared libraries (not quite SVR4 compatible)
Guido van Rossum25e85291996-02-25 05:02:29 +000049 __FreeBSD__ -- FreeBSD shared libraries
Guido van Rossum1ae940a1995-01-02 19:04:15 +000050
51 (The other WITH_* symbols are used only once, to set the
52 appropriate symbols.)
53*/
54
55/* Configure dynamic linking */
56
Guido van Rossumff4af061996-01-12 01:17:50 +000057#ifdef __hpux
58#define hpux
59#endif
60
Guido van Rossum1ae940a1995-01-02 19:04:15 +000061#ifdef hpux
62#define DYNAMIC_LINK
63#include <errno.h>
64typedef void (*dl_funcptr)();
65#define _DL_FUNCPTR_DEFINED 1
66#define SHORT_EXT ".sl"
67#define LONG_EXT "module.sl"
68#endif
69
Guido van Rossum25e85291996-02-25 05:02:29 +000070#if defined(__NetBSD__) || defined(__FreeBSD__)
Guido van Rossum46c76a61995-01-20 16:53:54 +000071#define DYNAMIC_LINK
72#define USE_SHLIB
73
74#define dlerror() "error in dynamic linking"
75#endif
76
Guido van Rossum0fbec641995-02-27 10:15:36 +000077#ifdef __WIN32__
78#define NT
79#endif
80
Guido van Rossumdadc8241996-05-23 22:51:40 +000081#ifdef MS_WIN16
82#define WIN16_DL
83#endif
84
85#if defined(NT) || defined(WIN16_DL)
Guido van Rossum1ae940a1995-01-02 19:04:15 +000086#define DYNAMIC_LINK
87#include <windows.h>
88typedef FARPROC dl_funcptr;
89#define _DL_FUNCPTR_DEFINED
Guido van Rossum5fb1da71995-01-07 12:36:02 +000090#define SHORT_EXT ".pyd"
Guido van Rossume71a9471996-04-09 02:39:15 +000091#define LONG_EXT ".dll"
Guido van Rossum1ae940a1995-01-02 19:04:15 +000092#endif
93
Guido van Rossum75f288d1995-06-14 22:07:26 +000094#ifdef NeXT
Guido van Rossum1ae940a1995-01-02 19:04:15 +000095#define DYNAMIC_LINK
96#define USE_RLD
97#endif
98
99#ifdef WITH_SGI_DL
100#define DYNAMIC_LINK
101#define USE_DL
102#endif
103
104#ifdef WITH_DL_DLD
105#define DYNAMIC_LINK
106#define USE_DL
107#endif
108
Guido van Rossum6a75d261995-02-18 14:51:15 +0000109#ifdef __CFM68K__
Jack Jansen5d9acb61995-06-14 14:54:25 +0000110#define USE_MAC_DYNAMIC_LOADING
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000111#endif
112
Jack Jansen5d9acb61995-06-14 14:54:25 +0000113#ifdef USE_MAC_DYNAMIC_LOADING
Jack Jansen4e043731995-02-13 22:42:34 +0000114#define DYNAMIC_LINK
Guido van Rossum6a75d261995-02-18 14:51:15 +0000115#define SHORT_EXT ".slb"
116#define LONG_EXT "module.slb"
Jack Jansen4e043731995-02-13 22:42:34 +0000117#ifndef _DL_FUNCPTR_DEFINED
118typedef void (*dl_funcptr)();
119#endif
120#endif
121
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000122#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
123#define DYNAMIC_LINK
124#define USE_SHLIB
125#endif
126
127#ifdef _AIX
128#define DYNAMIC_LINK
129#include <sys/ldr.h>
130typedef void (*dl_funcptr)();
131#define _DL_FUNCPTR_DEFINED
132static void aix_loaderror(char *name);
133#endif
134
135#ifdef DYNAMIC_LINK
136
137#ifdef USE_SHLIB
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000138#include <sys/types.h>
139#include <sys/stat.h>
Guido van Rossum25e85291996-02-25 05:02:29 +0000140#if defined(__NetBSD__) || defined(__FreeBSD__)
Guido van Rossum46c76a61995-01-20 16:53:54 +0000141#include <nlist.h>
142#include <link.h>
143#else
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000144#include <dlfcn.h>
Guido van Rossum46c76a61995-01-20 16:53:54 +0000145#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000146#ifndef _DL_FUNCPTR_DEFINED
147typedef void (*dl_funcptr)();
148#endif
149#ifndef RTLD_LAZY
150#define RTLD_LAZY 1
151#endif
152#define SHORT_EXT ".so"
153#define LONG_EXT "module.so"
154#endif /* USE_SHLIB */
155
156#if defined(USE_DL) || defined(hpux)
157#include "dl.h"
158#endif
159
Jack Jansen5d9acb61995-06-14 14:54:25 +0000160#ifdef USE_MAC_DYNAMIC_LOADING
Jack Jansen0a72e8d1995-10-23 13:54:01 +0000161#include <Aliases.h>
Jack Jansen4e043731995-02-13 22:42:34 +0000162#include <CodeFragments.h>
Jack Janseneceb3e31995-06-27 13:15:15 +0000163#ifdef SYMANTEC__CFM68K__ /* Really just an older version of Universal Headers */
Guido van Rossum6a75d261995-02-18 14:51:15 +0000164#define CFragConnectionID ConnectionID
165#define kLoadCFrag 0x01
166#endif
Jack Jansen4e043731995-02-13 22:42:34 +0000167#include <Files.h>
168#include "macdefs.h"
169#include "macglue.h"
170#endif
171
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000172#ifdef USE_RLD
173#include <mach-o/rld.h>
174#define FUNCNAME_PATTERN "_init%.200s"
175#ifndef _DL_FUNCPTR_DEFINED
176typedef void (*dl_funcptr)();
177#endif
178#endif /* USE_RLD */
179
180extern char *getprogramname();
181
182#ifndef FUNCNAME_PATTERN
Guido van Rossum25e85291996-02-25 05:02:29 +0000183#if defined(__hp9000s300) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__BORLANDC__)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000184#define FUNCNAME_PATTERN "_init%.200s"
185#else
186#define FUNCNAME_PATTERN "init%.200s"
187#endif
188#endif
189
190#if !defined(SHORT_EXT) && !defined(LONG_EXT)
191#define SHORT_EXT ".o"
192#define LONG_EXT "module.o"
193#endif /* !SHORT_EXT && !LONG_EXT */
194
195#endif /* DYNAMIC_LINK */
196
Guido van Rossum6a75d261995-02-18 14:51:15 +0000197/* Max length of module suffix searched for -- accommodates "module.slb" */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000198#ifndef MAXSUFFIXSIZE
Jack Jansen4e043731995-02-13 22:42:34 +0000199#define MAXSUFFIXSIZE 12
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000200#endif
201
202/* Pass it on to import.c */
203int import_maxsuffixsize = MAXSUFFIXSIZE;
204
205struct filedescr import_filetab[] = {
206#ifdef SHORT_EXT
207 {SHORT_EXT, "rb", C_EXTENSION},
208#endif /* !SHORT_EXT */
209#ifdef LONG_EXT
210 {LONG_EXT, "rb", C_EXTENSION},
211#endif /* !LONG_EXT */
212 {".py", "r", PY_SOURCE},
213 {".pyc", "rb", PY_COMPILED},
214 {0, 0}
215};
216
217object *
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000218load_dynamic_module(name, pathname, fp)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000219 char *name;
220 char *pathname;
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000221 FILE *fp;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000222{
223#ifndef DYNAMIC_LINK
224 err_setstr(ImportError, "dynamically linked modules not supported");
225 return NULL;
226#else
227 object *m;
228 char funcname[258];
229 dl_funcptr p = NULL;
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000230#ifdef USE_SHLIB
231 static struct {
232 dev_t dev;
233 ino_t ino;
234 void *handle;
235 } handles[128];
236 static int nhandles = 0;
237#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000238 sprintf(funcname, FUNCNAME_PATTERN, name);
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000239#ifdef USE_SHLIB
240 if (fp != NULL) {
241 int i;
242 struct stat statb;
243 fstat(fileno(fp), &statb);
244 for (i = 0; i < nhandles; i++) {
245 if (statb.st_dev == handles[i].dev &&
246 statb.st_ino == handles[i].ino) {
247 p = (dl_funcptr) dlsym(handles[i].handle,
248 funcname);
249 goto got_it;
250 }
251 }
252 if (nhandles < 128) {
253 handles[nhandles].dev = statb.st_dev;
254 handles[nhandles].ino = statb.st_ino;
255 }
256 }
257#endif /* USE_SHLIB */
Jack Jansen5d9acb61995-06-14 14:54:25 +0000258#ifdef USE_MAC_DYNAMIC_LOADING
259 /*
260 ** Dynamic loading of CFM shared libraries on the Mac.
261 ** The code has become more convoluted than it was, because we want to be able
262 ** to put multiple modules in a single file. For this reason, we have to determine
263 ** the fragment name, and we cannot use the library entry point but we have to locate
264 ** the correct init routine "by hand".
265 */
Jack Jansen4e043731995-02-13 22:42:34 +0000266 {
267 FSSpec libspec;
268 CFragConnectionID connID;
Guido van Rossum6a75d261995-02-18 14:51:15 +0000269 Ptr mainAddr;
270 Str255 errMessage;
271 OSErr err;
Jack Jansen5d9acb61995-06-14 14:54:25 +0000272 Boolean isfolder, didsomething;
273 char buf[512];
274 Str63 fragname;
275 Ptr symAddr;
276 CFragSymbolClass class;
Jack Jansen4e043731995-02-13 22:42:34 +0000277
Jack Jansen5d9acb61995-06-14 14:54:25 +0000278 /* First resolve any aliases to find the real file */
Jack Jansen4e043731995-02-13 22:42:34 +0000279 (void)FSMakeFSSpec(0, 0, Pstring(pathname), &libspec);
Jack Jansen5d9acb61995-06-14 14:54:25 +0000280 err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
281 if ( err ) {
282 sprintf(buf, "%s: %s", pathname, PyMac_StrError(err));
283 err_setstr(ImportError, buf);
284 return NULL;
285 }
286 /* Next, determine the fragment name, by stripping '.slb' and 'module' */
287 memcpy(fragname+1, libspec.name+1, libspec.name[0]);
288 fragname[0] = libspec.name[0];
289 if( strncmp((char *)(fragname+1+fragname[0]-4), ".slb", 4) == 0 )
290 fragname[0] -= 4;
291 if ( strncmp((char *)(fragname+1+fragname[0]-6), "module", 6) == 0 )
292 fragname[0] -= 6;
293 /* Load the fragment (or return the connID if it is already loaded */
294 err = GetDiskFragment(&libspec, 0, 0, fragname,
Guido van Rossum6a75d261995-02-18 14:51:15 +0000295 kLoadCFrag, &connID, &mainAddr,
296 errMessage);
Jack Jansen4e043731995-02-13 22:42:34 +0000297 if ( err ) {
Guido van Rossum3097c3a1995-02-21 21:02:46 +0000298 sprintf(buf, "%.*s: %s", errMessage[0], errMessage+1, PyMac_StrError(err));
Jack Jansen4e043731995-02-13 22:42:34 +0000299 err_setstr(ImportError, buf);
300 return NULL;
301 }
Jack Jansen5d9acb61995-06-14 14:54:25 +0000302 /* Locate the address of the correct init function */
303 err = FindSymbol(connID, Pstring(funcname), &symAddr, &class);
304 if ( err ) {
305 sprintf(buf, "%s: %s", funcname, PyMac_StrError(err));
306 err_setstr(ImportError, buf);
307 return NULL;
308 }
309 p = (dl_funcptr)symAddr;
Jack Jansen4e043731995-02-13 22:42:34 +0000310 }
Jack Jansen5d9acb61995-06-14 14:54:25 +0000311#endif /* USE_MAC_DYNAMIC_LOADING */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000312#ifdef USE_SHLIB
313 {
314#ifdef RTLD_NOW
315 /* RTLD_NOW: resolve externals now
316 (i.e. core dump now if some are missing) */
317 void *handle = dlopen(pathname, RTLD_NOW);
318#else
319 void *handle;
320 if (verbose)
321 printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
322 handle = dlopen(pathname, RTLD_LAZY);
323#endif /* RTLD_NOW */
324 if (handle == NULL) {
325 err_setstr(ImportError, dlerror());
326 return NULL;
327 }
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000328 if (fp != NULL && nhandles < 128)
329 handles[nhandles++].handle = handle;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000330 p = (dl_funcptr) dlsym(handle, funcname);
331 }
332#endif /* USE_SHLIB */
333#ifdef _AIX
334 p = (dl_funcptr) load(pathname, 1, 0);
335 if (p == NULL) {
336 aix_loaderror(pathname);
337 return NULL;
338 }
339#endif /* _AIX */
340#ifdef NT
341 {
342 HINSTANCE hDLL;
343 hDLL = LoadLibrary(pathname);
344 if (hDLL==NULL){
Guido van Rossum11a3f0c21995-07-18 14:40:09 +0000345 char errBuf[256];
346 unsigned int errorCode;
347
348 /* Get an error string from Win32 error code */
349 char theInfo[256]; /* Pointer to error text from system */
350 int theLength; /* Length of error text */
351
352 errorCode = GetLastError();
353
354 theLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, /* flags */
355 NULL, /* message source */
356 errorCode, /* the message (error) ID */
357 0, /* default language environment */
358 (LPTSTR) theInfo, /* the buffer */
359 sizeof(theInfo), /* the buffer size */
360 NULL); /* no additional format args. */
361
362 /* Problem: could not get the error message. This should not happen if called correctly. */
363 if (theLength == 0) {
364 sprintf(errBuf, "DLL load failed with error code %d", errorCode);
365 } else {
366 int len;
367 /* For some reason a \r\n is appended to the text */
368 if (theLength >= 2 && theInfo[theLength-2] == '\r' && theInfo[theLength-1] == '\n') {
369 theLength -= 2;
370 theInfo[theLength] = '\0';
371 }
372 strcpy(errBuf, "DLL load failed: ");
373 len = strlen(errBuf);
374 strncpy(errBuf+len, theInfo, sizeof(errBuf)-len);
375 errBuf[sizeof(errBuf)-1] = '\0';
376 }
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000377 err_setstr(ImportError, errBuf);
378 return NULL;
379 }
380 p = GetProcAddress(hDLL, funcname);
381 }
382#endif /* NT */
Guido van Rossumdadc8241996-05-23 22:51:40 +0000383#ifdef WIN16_DL
384 {
385 HINSTANCE hDLL;
386 hDLL = LoadLibrary(pathname);
387 if (hDLL < HINSTANCE_ERROR){
388 char errBuf[256];
389 sprintf(errBuf, "DLL load failed with error code %d", hDLL);
390 err_setstr(ImportError, errBuf);
391 return NULL;
392 }
393 p = GetProcAddress(hDLL, funcname);
394 }
395#endif /* WIN16_DL */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000396#ifdef USE_DL
397 p = dl_loadmod(getprogramname(), pathname, funcname);
398#endif /* USE_DL */
399#ifdef USE_RLD
400 {
401 NXStream *errorStream;
402 struct mach_header *new_header;
403 const char *filenames[2];
404 long ret;
405 unsigned long ptr;
406
407 errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
408 filenames[0] = pathname;
409 filenames[1] = NULL;
410 ret = rld_load(errorStream, &new_header,
411 filenames, NULL);
412
413 /* extract the error messages for the exception */
414 if(!ret) {
415 char *streamBuf;
416 int len, maxLen;
417
418 NXPutc(errorStream, (char)0);
419
420 NXGetMemoryBuffer(errorStream,
421 &streamBuf, &len, &maxLen);
422 err_setstr(ImportError, streamBuf);
423 }
424
425 if(ret && rld_lookup(errorStream, funcname, &ptr))
426 p = (dl_funcptr) ptr;
427
428 NXCloseMemory(errorStream, NX_FREEBUFFER);
429
430 if(!ret)
431 return NULL;
432 }
433#endif /* USE_RLD */
434#ifdef hpux
435 {
436 shl_t lib;
437 int flags;
438
439 flags = BIND_DEFERRED;
440 if (verbose)
441 {
442 flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
443 printf("shl_load %s\n",pathname);
444 }
445 lib = shl_load(pathname, flags, 0);
446 if (lib == NULL)
447 {
448 char buf[256];
449 if (verbose)
450 perror(pathname);
451 sprintf(buf, "Failed to load %.200s", pathname);
452 err_setstr(ImportError, buf);
453 return NULL;
454 }
455 if (verbose)
456 printf("shl_findsym %s\n", funcname);
457 shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
458 if (p == NULL && verbose)
459 perror(funcname);
460 }
461#endif /* hpux */
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000462 got_it:
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000463 if (p == NULL) {
464 err_setstr(ImportError,
465 "dynamic module does not define init function");
466 return NULL;
467 }
468 (*p)();
469
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000470 m = dictlookup(import_modules, name);
471 if (m == NULL) {
472 if (err_occurred() == NULL)
473 err_setstr(SystemError,
474 "dynamic module not initialized properly");
475 return NULL;
476 }
477 if (verbose)
478 fprintf(stderr,
479 "import %s # dynamically loaded from %s\n",
480 name, pathname);
481 INCREF(m);
482 return m;
483#endif /* DYNAMIC_LINK */
484}
485
486
487#ifdef _AIX
488
489#include <ctype.h> /* for isdigit() */
490#include <errno.h> /* for global errno */
491#include <string.h> /* for strerror() */
492
493void aix_loaderror(char *pathname)
494{
495
496 char *message[8], errbuf[1024];
497 int i,j;
498
499 struct errtab {
500 int errno;
501 char *errstr;
502 } load_errtab[] = {
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000503 {L_ERROR_TOOMANY, "too many errors, rest skipped."},
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000504 {L_ERROR_NOLIB, "can't load library:"},
505 {L_ERROR_UNDEF, "can't find symbol in library:"},
506 {L_ERROR_RLDBAD,
507 "RLD index out of range or bad relocation type:"},
508 {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
509 {L_ERROR_MEMBER,
510 "file not an archive or does not contain requested member:"},
511 {L_ERROR_TYPE, "symbol table mismatch:"},
512 {L_ERROR_ALIGN, "text allignment in file is wrong."},
513 {L_ERROR_SYSTEM, "System error:"},
514 {L_ERROR_ERRNO, NULL}
515 };
516
517#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
518#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
519
520 sprintf(errbuf, " from module %.200s ", pathname);
521
522 if (!loadquery(1, &message[0], sizeof(message)))
523 ERRBUF_APPEND(strerror(errno));
524 for(i = 0; message[i] && *message[i]; i++) {
525 int nerr = atoi(message[i]);
526 for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
527 if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
528 ERRBUF_APPEND(load_errtab[i].errstr);
529 }
530 while (isdigit(*message[i])) message[i]++ ;
531 ERRBUF_APPEND(message[i]);
532 ERRBUF_APPEND("\n");
533 }
534 errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
535 err_setstr(ImportError, errbuf);
536 return;
537}
538
539#endif /* _AIX */