1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
/* dlutils.c - handy functions and definitions for dl_*.xs files
*
* Currently this file is simply #included into dl_*.xs/.c files.
* It should really be split into a dlutils.h and dlutils.c
*
* Modified:
* 29th Feburary 2000 - Alan Burlison: Added functionality to close dlopen'd
* files when the interpreter exits
*/
#ifndef START_MY_CXT /* Some IDEs try compiling this standalone. */
# include "EXTERN.h"
# include "perl.h"
# include "XSUB.h"
#endif
#ifndef XS_VERSION
# define XS_VERSION "0"
#endif
#define MY_CXT_KEY "DynaLoader::_guts" XS_VERSION
typedef struct {
SV* x_dl_last_error; /* pointer to allocated memory for
last error message */
int x_dl_nonlazy; /* flag for immediate rather than lazy
linking (spots unresolved symbol) */
#ifdef DL_LOADONCEONLY
HV * x_dl_loaded_files; /* only needed on a few systems */
#endif
#ifdef DL_CXT_EXTRA
my_cxtx_t x_dl_cxtx; /* extra platform-specific data */
#endif
#ifdef DEBUGGING
int x_dl_debug; /* value copied from $DynaLoader::dl_debug */
#endif
} my_cxt_t;
START_MY_CXT
#define dl_last_error (SvPVX(MY_CXT.x_dl_last_error))
#define dl_nonlazy (MY_CXT.x_dl_nonlazy)
#ifdef DL_LOADONCEONLY
#define dl_loaded_files (MY_CXT.x_dl_loaded_files)
#endif
#ifdef DL_CXT_EXTRA
#define dl_cxtx (MY_CXT.x_dl_cxtx)
#endif
#ifdef DEBUGGING
#define dl_debug (MY_CXT.x_dl_debug)
#endif
#ifdef DEBUGGING
#define DLDEBUG(level,code) \
STMT_START { \
dMY_CXT; \
if (dl_debug>=level) { code; } \
} STMT_END
#else
#define DLDEBUG(level,code) NOOP
#endif
#ifdef DL_UNLOAD_ALL_AT_EXIT
/* Close all dlopen'd files */
static void
dl_unload_all_files(pTHX_ void *unused)
{
CV *sub;
AV *dl_librefs;
SV *dl_libref;
if ((sub = get_cvs("DynaLoader::dl_unload_file", 0)) != NULL) {
dl_librefs = get_av("DynaLoader::dl_librefs", 0);
while ((dl_libref = av_pop(dl_librefs)) != &PL_sv_undef) {
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(dl_libref));
PUTBACK;
call_sv((SV*)sub, G_DISCARD | G_NODEBUG);
FREETMPS;
LEAVE;
}
}
}
#endif
static void
dl_generic_private_init(pTHX) /* called by dl_*.xs dl_private_init() */
{
char *perl_dl_nonlazy;
MY_CXT_INIT;
MY_CXT.x_dl_last_error = newSVpvn("", 0);
dl_nonlazy = 0;
#ifdef DL_LOADONCEONLY
dl_loaded_files = NULL;
#endif
#ifdef DEBUGGING
{
SV *sv = get_sv("DynaLoader::dl_debug", 0);
dl_debug = sv ? SvIV(sv) : 0;
}
#endif
if ( (perl_dl_nonlazy = getenv("PERL_DL_NONLAZY")) != NULL )
dl_nonlazy = atoi(perl_dl_nonlazy);
if (dl_nonlazy)
DLDEBUG(1,PerlIO_printf(Perl_debug_log, "DynaLoader bind mode is 'non-lazy'\n"));
#ifdef DL_LOADONCEONLY
if (!dl_loaded_files)
dl_loaded_files = newHV(); /* provide cache for dl_*.xs if needed */
#endif
#ifdef DL_UNLOAD_ALL_AT_EXIT
call_atexit(&dl_unload_all_files, (void*)0);
#endif
}
#ifndef SYMBIAN
/* SaveError() takes printf style args and saves the result in dl_last_error */
static void
SaveError(pTHX_ const char* pat, ...)
{
dMY_CXT;
va_list args;
SV *msv;
const char *message;
STRLEN len;
/* This code is based on croak/warn, see mess() in util.c */
va_start(args, pat);
msv = vmess(pat, &args);
va_end(args);
message = SvPV(msv,len);
len++; /* include terminating null char */
/* Copy message into dl_last_error (including terminating null char) */
sv_setpvn(MY_CXT.x_dl_last_error, message, len) ;
DLDEBUG(2,PerlIO_printf(Perl_debug_log, "DynaLoader: stored error msg '%s'\n",dl_last_error));
}
#endif
|