view Python/import.c @ 73:3028acaa56b0 legacy-trunk

Compile class definitions. Document and fix code generation for try statements. Use two bytes for all arguments. Avoid duplicate entries in lists of constants and names.
author Guido van Rossum <guido@python.org>
date Sun, 18 Nov 1990 17:35:03 +0000
parents f28ac7f621c7
children bc244df20251
line wrap: on
line source

/* 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;
}

static void
use_module(ctx, d)
	context *ctx;
	object *d;
{
	INCREF(d);
	DECREF(ctx->ctx_locals);
	ctx->ctx_locals = d;
	INCREF(d);
	DECREF(ctx->ctx_globals);
	ctx->ctx_globals = d;
}

static void
define_module(ctx, name)
	context *ctx;
	char *name;
{
	object *m;
	m = new_module(name);
	if (m == NULL) {
		puterrno(ctx);
		return;
	}
	use_module(ctx, getmoduledict(m));
	DECREF(m);
}

static 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;
	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) {
		name_error(ctx, name);
		return NULL;
	}
	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;
}

object *
reload_module(ctx, m)
	context *ctx;
	object *m;
{
	char *name;
	FILE *fp;
	node *n;
	int err;
	object *d;
	object *save_locals, *save_globals;
	if (m == NULL || !is_moduleobject(m)) {
		type_error(ctx, "reload() argument must be module");
		return NULL;
	}
	/* XXX Ought to check for builtin module */
	name = getmodulename(m);
	fp = open_module(name, ".py");
	if (fp == NULL) {
		error(ctx, "reload() cannot find module source file");
		return NULL;
	}
	err = parseinput(fp, file_input, &n);
	fclose(fp);
	if (err != E_DONE) {
		input_error(ctx, err);
		return NULL;
	}
	d = newdictobject();
	if (d == NULL)
		return NULL;
	setmoduledict(m, d);
	save_locals = ctx->ctx_locals;
	INCREF(save_locals);
	save_globals = ctx->ctx_globals;
	INCREF(save_globals);
	use_module(ctx, d);
	exec_node(ctx, n);
	DECREF(ctx->ctx_locals);
	ctx->ctx_locals = save_locals;
	DECREF(ctx->ctx_globals);
	ctx->ctx_globals = save_globals;
	if (ctx->ctx_exception)
		return NULL;
	INCREF(None);
	return None;
}