Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e25c256

Browse files
committed
Support for dynamic loading added.
1 parent 450ed49 commit e25c256

1 file changed

Lines changed: 132 additions & 5 deletions

File tree

Python/import.c

Lines changed: 132 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3737
#include "compile.h"
3838
#include "ceval.h"
3939

40+
#ifdef DEBUG
41+
#define D(x) x
42+
#else
43+
#define D(x)
44+
#endif
45+
46+
#ifdef USE_DL
47+
#include "dl.h"
48+
49+
static char *getbinaryname();
50+
#endif
51+
4052
/* Magic word to reject pre-0.9.4 .pyc files */
4153

4254
#define MAGIC 0x949494L
@@ -93,19 +105,38 @@ add_module(name)
93105
return m;
94106
}
95107

108+
/* Suffixes used by open_module: */
109+
110+
#define PY_SUFFIX ".py"
111+
#ifdef USE_DL
112+
#define O_SUFFIX "module.o"
113+
#endif
114+
115+
/* Find and open a module file, using sys.path.
116+
Return a NULL pointer if no module file is found.
117+
When dynamic loading is enabled, the contents of namebuf
118+
is important when NULL is returned: if namebuf[0] != '\0'
119+
a dl-able object file was found and namebuf is its pathname. */
120+
96121
static FILE *
97-
open_module(name, suffix, namebuf)
122+
open_module(name, namebuf)
98123
char *name;
99-
char *suffix;
100124
char *namebuf; /* XXX No buffer overflow checks! */
101125
{
102126
object *path;
103127
FILE *fp;
104128

105129
path = sysget("path");
106130
if (path == NULL || !is_listobject(path)) {
131+
/* No path -- at least try current directory */
132+
#ifdef USE_DL
133+
strcpy(namebuf, name);
134+
strcat(namebuf, O_SUFFIX);
135+
if (getmtime(namebuf) > 0)
136+
return NULL;
137+
#endif
107138
strcpy(namebuf, name);
108-
strcat(namebuf, suffix);
139+
strcat(namebuf, PY_SUFFIX);
109140
fp = fopen(namebuf, "r");
110141
}
111142
else {
@@ -121,13 +152,21 @@ open_module(name, suffix, namebuf)
121152
len = getstringsize(v);
122153
if (len > 0 && namebuf[len-1] != SEP)
123154
namebuf[len++] = SEP;
155+
#ifdef USE_DL
124156
strcpy(namebuf+len, name);
125-
strcat(namebuf, suffix);
157+
strcat(namebuf, O_SUFFIX);
158+
if (getmtime(namebuf) > 0)
159+
return NULL;
160+
#endif
161+
strcpy(namebuf+len, name);
162+
strcat(namebuf, PY_SUFFIX);
126163
fp = fopen(namebuf, "r");
127164
if (fp != NULL)
128165
break;
129166
}
130167
}
168+
if (fp == NULL)
169+
namebuf[0] = '\0';
131170
return fp;
132171
}
133172

@@ -147,8 +186,35 @@ get_module(m, name, m_ret)
147186
long mtime;
148187
extern long getmtime();
149188

150-
fp = open_module(name, ".py", namebuf);
189+
fp = open_module(name, namebuf);
151190
if (fp == NULL) {
191+
#ifdef USE_DL
192+
if (namebuf[0] != '\0') {
193+
char funcname[258];
194+
dl_funcptr p;
195+
D(fprintf(stderr, "Found %s\n", namebuf));
196+
sprintf(funcname, "init%s", name);
197+
p = dl_loadmod(getbinaryname(), namebuf, funcname);
198+
if (p == NULL) {
199+
D(fprintf(stderr, "dl_loadmod failed\n"));
200+
}
201+
else {
202+
(*p)();
203+
*m_ret = m = dictlookup(modules, name);
204+
if (m == NULL) {
205+
err_setstr(SystemError,
206+
"dynamic module missing");
207+
return NULL;
208+
}
209+
else {
210+
D(fprintf(stderr,
211+
"module %s loaded!\n", name));
212+
INCREF(None);
213+
return None;
214+
}
215+
}
216+
}
217+
#endif
152218
if (m == NULL) {
153219
sprintf(namebuf, "no module named %.200s", name);
154220
err_setstr(ImportError, namebuf);
@@ -338,3 +404,64 @@ init_builtin(name)
338404
}
339405
return 0;
340406
}
407+
408+
#ifdef USE_DL
409+
410+
/* A function to find a filename for the currently executing binary.
411+
Because this is not directly available, we have to search for argv[0]
412+
along $PATH. But note that if argv[0] contains a slash anywhere,
413+
sh(1) doesn't search $PATH -- so neither do we! */
414+
415+
/* XXX This should be moved to a more system-specific file */
416+
417+
#include <sys/types.h>
418+
#include <sys/stat.h> /* For stat */
419+
420+
extern char *getenv();
421+
422+
extern char *argv0; /* In config.c */
423+
424+
/* Default path from sh(1) in Irix 4.0.1 */
425+
#define DEF_PATH ":/usr/sbin:/usr/bsd:/bin:/usr/bin:/usr/bin/X11"
426+
427+
static char *
428+
getbinaryname()
429+
{
430+
char *p, *q;
431+
char *path;
432+
static char buf[258];
433+
int i;
434+
struct stat st;
435+
436+
if (strchr(argv0, '/') != NULL) {
437+
D(fprintf(stderr, "binary includes slash: %s\n", argv0));
438+
return argv0;
439+
}
440+
path = getenv("PATH");
441+
if (path == NULL)
442+
path = DEF_PATH;
443+
p = q = path;
444+
for (;;) {
445+
while (*q && *q != ':')
446+
q++;
447+
i = q-p;
448+
strncpy(buf, p, i);
449+
if (q > p && q[-1] != '/')
450+
buf[i++] = '/';
451+
strcpy(buf+i, argv0);
452+
if (stat(buf, &st) >= 0) {
453+
if (S_ISREG(st.st_mode) &&
454+
(st.st_mode & 0111)) {
455+
D(fprintf(stderr, "found binary: %s\n", buf));
456+
return buf;
457+
}
458+
}
459+
if (!*q)
460+
break;
461+
p = ++q;
462+
}
463+
D(fprintf(stderr, "can't find binary: %s\n", argv0));
464+
return argv0;
465+
}
466+
467+
#endif

0 commit comments

Comments
 (0)