| /* Module definition and import implementation */ |
| |
| #include <stdio.h> |
| #include "string.h" |
| |
| #include "PROTO.h" |
| #include "object.h" |
| #include "stringobject.h" |
| #include "listobject.h" |
| #include "dictobject.h" |
| #include "moduleobject.h" |
| #include "node.h" |
| #include "context.h" |
| #include "token.h" |
| #include "graminit.h" |
| #include "run.h" |
| #include "support.h" |
| #include "import.h" |
| #include "errcode.h" |
| #include "sysmodule.h" |
| |
| /* Define pathname separator and delimiter in $PYTHONPATH */ |
| |
| #ifdef THINK_C |
| #define SEP ':' |
| #define DELIM ' ' |
| #endif |
| |
| #ifndef SEP |
| #define SEP '/' |
| #endif |
| |
| #ifndef DELIM |
| #define DELIM ':' |
| #endif |
| |
| void |
| initimport() |
| { |
| object *v; |
| if ((v = newdictobject()) == NULL) |
| fatal("no mem for module table"); |
| if (sysset("modules", v) != 0) |
| fatal("can't assign sys.modules"); |
| } |
| |
| object * |
| new_module(name) |
| char *name; |
| { |
| object *m; |
| object *mtab; |
| mtab = sysget("modules"); |
| if (mtab == NULL || !is_dictobject(mtab)) { |
| errno = EBADF; |
| return NULL; |
| } |
| m = newmoduleobject(name); |
| if (m == NULL) |
| return NULL; |
| if (dictinsert(mtab, name, m) != 0) { |
| DECREF(m); |
| return NULL; |
| } |
| return m; |
| } |
| |
| void |
| define_module(ctx, name) |
| context *ctx; |
| char *name; |
| { |
| object *m, *d; |
| m = new_module(name); |
| if (m == NULL) { |
| puterrno(ctx); |
| return; |
| } |
| d = getmoduledict(m); |
| INCREF(d); |
| DECREF(ctx->ctx_locals); |
| ctx->ctx_locals = d; |
| INCREF(d); |
| DECREF(ctx->ctx_globals); |
| ctx->ctx_globals = d; |
| DECREF(m); |
| } |
| |
| object * |
| parsepath(path, delim) |
| char *path; |
| int delim; |
| { |
| int i, n; |
| char *p; |
| object *v, *w; |
| |
| n = 1; |
| p = path; |
| while ((p = strchr(p, delim)) != NULL) { |
| n++; |
| p++; |
| } |
| v = newlistobject(n); |
| if (v == NULL) |
| return NULL; |
| for (i = 0; ; i++) { |
| p = strchr(path, delim); |
| if (p == NULL) |
| p = strchr(path, '\0'); /* End of string */ |
| w = newsizedstringobject(path, (int) (p - path)); |
| if (w == NULL) { |
| DECREF(v); |
| return NULL; |
| } |
| setlistitem(v, i, w); |
| if (*p == '\0') |
| break; |
| path = p+1; |
| } |
| return v; |
| } |
| |
| void |
| setpythonpath(path) |
| char *path; |
| { |
| object *v; |
| if ((v = parsepath(path, DELIM)) != NULL) { |
| if (sysset("path", v) != 0) |
| fatal("can't assign sys.path"); |
| DECREF(v); |
| } |
| } |
| |
| static FILE * |
| open_module(name, suffix) |
| char *name; |
| char *suffix; |
| { |
| object *path; |
| char namebuf[256]; |
| FILE *fp; |
| |
| path = sysget("path"); |
| if (path == NULL || !is_listobject(path)) { |
| strcpy(namebuf, name); |
| strcat(namebuf, suffix); |
| fp = fopen(namebuf, "r"); |
| } |
| else { |
| int npath = getlistsize(path); |
| int i; |
| fp = NULL; |
| for (i = 0; i < npath; i++) { |
| object *v = getlistitem(path, i); |
| int len; |
| if (!is_stringobject(v)) |
| continue; |
| strcpy(namebuf, getstringvalue(v)); |
| len = getstringsize(v); |
| if (len > 0 && namebuf[len-1] != SEP) |
| namebuf[len++] = SEP; |
| strcpy(namebuf+len, name); /* XXX check for overflow */ |
| strcat(namebuf, suffix); /* XXX ditto */ |
| fp = fopen(namebuf, "r"); |
| if (fp != NULL) |
| break; |
| } |
| } |
| return fp; |
| } |
| |
| static object * |
| load_module(ctx, name) |
| context *ctx; |
| char *name; |
| { |
| object *m; |
| char **p; |
| FILE *fp; |
| node *n, *mh; |
| int err; |
| object *mtab; |
| object *save_locals, *save_globals; |
| |
| mtab = sysget("modules"); |
| if (mtab == NULL || !is_dictobject(mtab)) { |
| errno = EBADF; |
| return NULL; |
| } |
| fp = open_module(name, ".py"); |
| if (fp == NULL) { |
| /* XXX Compatibility hack */ |
| fprintf(stderr, |
| "Can't find '%s.py' in sys.path, trying '%s'\n", |
| name, name); |
| fp = open_module(name, ""); |
| } |
| if (fp == NULL) { |
| name_error(ctx, name); |
| return NULL; |
| } |
| #ifdef DEBUG |
| fprintf(stderr, "Reading module %s from file '%s'\n", name, namebuf); |
| #endif |
| err = parseinput(fp, file_input, &n); |
| fclose(fp); |
| if (err != E_DONE) { |
| input_error(ctx, err); |
| return NULL; |
| } |
| save_locals = ctx->ctx_locals; |
| INCREF(save_locals); |
| save_globals = ctx->ctx_globals; |
| INCREF(save_globals); |
| define_module(ctx, name); |
| exec_node(ctx, n); |
| DECREF(ctx->ctx_locals); |
| ctx->ctx_locals = save_locals; |
| DECREF(ctx->ctx_globals); |
| ctx->ctx_globals = save_globals; |
| /* XXX need to free the tree n here; except referenced defs */ |
| if (ctx->ctx_exception) { |
| dictremove(mtab, name); /* Undefine the module */ |
| return NULL; |
| } |
| m = dictlookup(mtab, name); |
| if (m == NULL) { |
| error(ctx, "module not defined after loading"); |
| return NULL; |
| } |
| return m; |
| } |
| |
| object * |
| import_module(ctx, name) |
| context *ctx; |
| char *name; |
| { |
| object *m; |
| object *mtab; |
| mtab = sysget("modules"); |
| if (mtab == NULL || !is_dictobject(mtab)) { |
| error(ctx, "bad sys.modules"); |
| return NULL; |
| } |
| if ((m = dictlookup(mtab, name)) == NULL) { |
| m = load_module(ctx, name); |
| } |
| return m; |
| } |