modsupport.c 9.58 KB
Newer Older
1
/***********************************************************
2 3
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
4 5 6

                        All Rights Reserved

7 8
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
9
provided that the above copyright notice appear in all copies and that
10
both that copyright notice and this permission notice appear in
11
supporting documentation, and that the names of Stichting Mathematisch
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
29 30 31

******************************************************************/

Guido van Rossum's avatar
Guido van Rossum committed
32 33
/* Module support implementation */

Guido van Rossum's avatar
Guido van Rossum committed
34
#include "allobjects.h"
Guido van Rossum's avatar
Guido van Rossum committed
35 36
#include "import.h"

37 38
#ifdef MPW /* MPW pushes 'extended' for float and double types with varargs */
typedef extended va_double;
39
#else
40 41 42
typedef double va_double;
#endif

Guido van Rossum's avatar
Guido van Rossum committed
43 44 45 46 47 48 49
/* initmodule4() parameters:
   - name is the module name
   - methods is the list of top-level functions
   - doc is the documentation string
   - passthrough is passed as self to functions defined in the module
   - api_version is the value of PYTHON_API_VERSION at the time the
     module was compiled
50
*/
51

Guido van Rossum's avatar
Guido van Rossum committed
52 53
static char api_version_warning[] =
"WARNING: Python C API version mismatch for module %s:\n\
54
  This Python has API version %d, module %s has version %d.\n";
Guido van Rossum's avatar
Guido van Rossum committed
55

Guido van Rossum's avatar
Guido van Rossum committed
56
object *
Guido van Rossum's avatar
Guido van Rossum committed
57
initmodule4(name, methods, doc, passthrough, module_api_version)
Guido van Rossum's avatar
Guido van Rossum committed
58 59
	char *name;
	struct methodlist *methods;
60
	char *doc;
61
	object *passthrough;
Guido van Rossum's avatar
Guido van Rossum committed
62
	int module_api_version;
Guido van Rossum's avatar
Guido van Rossum committed
63 64 65
{
	object *m, *d, *v;
	struct methodlist *ml;
Guido van Rossum's avatar
Guido van Rossum committed
66 67 68
	if (module_api_version != PYTHON_API_VERSION)
		fprintf(stderr, api_version_warning,
			name, PYTHON_API_VERSION, name, module_api_version);
Guido van Rossum's avatar
Guido van Rossum committed
69
	if ((m = add_module(name)) == NULL) {
Guido van Rossum's avatar
Guido van Rossum committed
70 71 72 73 74
		fprintf(stderr, "initializing module: %s\n", name);
		fatal("can't create a module");
	}
	d = getmoduledict(m);
	for (ml = methods; ml->ml_name != NULL; ml++) {
75
		v = newmethodobject(ml, passthrough);
Guido van Rossum's avatar
Guido van Rossum committed
76 77 78 79 80 81
		if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
			fprintf(stderr, "initializing module: %s\n", name);
			fatal("can't initialize module");
		}
		DECREF(v);
	}
82 83 84 85 86 87
	if (doc != NULL) {
		v = newstringobject(doc);
		if (v == NULL || dictinsert(d, "__doc__", v) != 0)
			fatal("can't add doc string");
		DECREF(v);
	}
Guido van Rossum's avatar
Guido van Rossum committed
88
	return m;
Guido van Rossum's avatar
Guido van Rossum committed
89 90 91
}


92
/* Helper for mkvalue() to scan the length of a format */
93 94 95 96 97 98 99 100 101

static int countformat PROTO((char *format, int endchar));
static int countformat(format, endchar)
	char *format;
	int endchar;
{
	int count = 0;
	int level = 0;
	while (level > 0 || *format != endchar) {
102 103
		switch (*format) {
		case '\0':
104 105 106
			/* Premature end */
			err_setstr(SystemError, "unmatched paren in format");
			return -1;
107 108 109
		case '(':
		case '[':
		case '{':
110 111 112
			if (level == 0)
				count++;
			level++;
113 114 115 116
			break;
		case ')':
		case ']':
		case '}':
117
			level--;
118 119
			break;
		case '#':
120
		case '&':
121 122 123 124 125 126 127 128 129
		case ',':
		case ':':
		case ' ':
		case '\t':
			break;
		default:
			if (level == 0)
				count++;
		}
130 131 132 133 134 135 136 137 138 139
		format++;
	}
	return count;
}


/* Generic function to create a value -- the inverse of getargs() */
/* After an original idea and first implementation by Steven Miale */

static object *do_mktuple PROTO((char**, va_list *, int, int));
140 141
static object *do_mklist PROTO((char**, va_list *, int, int));
static object *do_mkdict PROTO((char**, va_list *, int, int));
142 143
static object *do_mkvalue PROTO((char**, va_list *));

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

static object *
do_mkdict(p_format, p_va, endchar, n)
	char **p_format;
	va_list *p_va;
	int endchar;
	int n;
{
	object *d;
	int i;
	if (n < 0)
		return NULL;
	if ((d = newdictobject()) == NULL)
		return NULL;
	for (i = 0; i < n; i+= 2) {
		object *k, *v;
		k = do_mkvalue(p_format, p_va);
		if (k == NULL) {
			DECREF(d);
			return NULL;
		}
		v = do_mkvalue(p_format, p_va);
		if (v == NULL) {
			DECREF(k);
			DECREF(d);
			return NULL;
		}
		if (dict2insert(d, k, v) < 0) {
			DECREF(k);
			DECREF(v);
			DECREF(d);
			return NULL;
		}
	}
	if (d != NULL && **p_format != endchar) {
		DECREF(d);
		d = NULL;
		err_setstr(SystemError, "Unmatched paren in format");
	}
	else if (endchar)
		++*p_format;
	return d;
}

static object *
do_mklist(p_format, p_va, endchar, n)
	char **p_format;
	va_list *p_va;
	int endchar;
	int n;
{
	object *v;
	int i;
	if (n < 0)
		return NULL;
	if ((v = newlistobject(n)) == NULL)
		return NULL;
	for (i = 0; i < n; i++) {
		object *w = do_mkvalue(p_format, p_va);
		if (w == NULL) {
			DECREF(v);
			return NULL;
		}
		setlistitem(v, i, w);
	}
	if (v != NULL && **p_format != endchar) {
		DECREF(v);
		v = NULL;
		err_setstr(SystemError, "Unmatched paren in format");
	}
	else if (endchar)
		++*p_format;
	return v;
}

219
static object *
220 221 222 223 224 225
do_mktuple(p_format, p_va, endchar, n)
	char **p_format;
	va_list *p_va;
	int endchar;
	int n;
{
226
	object *v;
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
	int i;
	if (n < 0)
		return NULL;
	if ((v = newtupleobject(n)) == NULL)
		return NULL;
	for (i = 0; i < n; i++) {
		object *w = do_mkvalue(p_format, p_va);
		if (w == NULL) {
			DECREF(v);
			return NULL;
		}
		settupleitem(v, i, w);
	}
	if (v != NULL && **p_format != endchar) {
		DECREF(v);
		v = NULL;
		err_setstr(SystemError, "Unmatched paren in format");
	}
	else if (endchar)
		++*p_format;
	return v;
}

static object *
251 252 253 254
do_mkvalue(p_format, p_va)
	char **p_format;
	va_list *p_va;
{
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
	for (;;) {
		switch (*(*p_format)++) {
		case '(':
			return do_mktuple(p_format, p_va, ')',
					  countformat(*p_format, ')'));

		case '[':
			return do_mklist(p_format, p_va, ']',
					 countformat(*p_format, ']'));

		case '{':
			return do_mkdict(p_format, p_va, '}',
					 countformat(*p_format, '}'));

		case 'b':
		case 'h':
		case 'i':
			return newintobject((long)va_arg(*p_va, int));

		case 'l':
			return newintobject((long)va_arg(*p_va, long));

		case 'f':
		case 'd':
279
			return newfloatobject((double)va_arg(*p_va, va_double));
280 281

		case 'c':
282 283 284 285 286
		{
			char p[1];
			p[0] = va_arg(*p_va, int);
			return newsizedstringobject(p, 1);
		}
287 288 289

		case 's':
		case 'z':
290
		{
291
			object *v;
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
			char *str = va_arg(*p_va, char *);
			int n;
			if (**p_format == '#') {
				++*p_format;
				n = va_arg(*p_va, int);
			}
			else
				n = -1;
			if (str == NULL) {
				v = None;
				INCREF(v);
			}
			else {
				if (n < 0)
					n = strlen(str);
				v = newsizedstringobject(str, n);
			}
309
			return v;
310
		}
311 312 313

		case 'S':
		case 'O':
314
		if (**p_format == '&') {
315
			typedef object *(*converter) PROTO((void *));
316 317 318 319 320 321
			converter func = va_arg(*p_va, converter);
			void *arg = va_arg(*p_va, void *);
			++*p_format;
			return (*func)(arg);
		}
		else {
322 323 324 325 326
			object *v;
			v = va_arg(*p_va, object *);
			if (v != NULL)
				INCREF(v);
			else if (!err_occurred())
327 328 329 330 331 332 333 334
				/* If a NULL was passed
				 * because a call that should
				 * have constructed a value
				 * failed, that's OK, and we
				 * pass the error on; but if
				 * no error occurred it's not
				 * clear that the caller knew
				 * what she was doing. */
335 336 337
				err_setstr(SystemError,
					   "NULL object passed to mkvalue");
			return v;
338
		}
339 340 341 342 343 344 345 346 347 348 349 350 351

		case ':':
		case ',':
		case ' ':
		case '\t':
			break;

		default:
			err_setstr(SystemError,
				   "bad format char passed to mkvalue");
			return NULL;

		}
352 353 354
	}
}

355

356
#ifdef HAVE_STDARG_PROTOTYPES
357 358 359 360 361 362
/* VARARGS 2 */
object *mkvalue(char *format, ...)
#else
/* VARARGS */
object *mkvalue(va_alist) va_dcl
#endif
363
{
364 365
	va_list va;
	object* retval;
366
#ifdef HAVE_STDARG_PROTOTYPES
367 368 369 370 371 372
	va_start(va, format);
#else
	char *format;
	va_start(va);
	format = va_arg(va, char *);
#endif
373
	retval = vmkvalue(format, va);
374 375
	va_end(va);
	return retval;
376
}
377 378 379 380 381 382 383 384

object *
vmkvalue(format, va)
	char *format;
	va_list va;
{
	char *f = format;
	int n = countformat(f, '\0');
385 386 387 388 389 390 391 392
	va_list lva;

#ifdef VA_LIST_IS_ARRAY
	memcpy(lva, va, sizeof(va_list));
#else
	lva = va;
#endif

393 394 395 396 397 398 399
	if (n < 0)
		return NULL;
	if (n == 0) {
		INCREF(None);
		return None;
	}
	if (n == 1)
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
		return do_mkvalue(&f, &lva);
	return do_mktuple(&f, &lva, '\0', n);
}


#ifdef HAVE_STDARG_PROTOTYPES
object *
PyEval_CallFunction(object *obj, char *format, ...)
#else
object *
PyEval_CallFunction(obj, format, va_alist)
	object *obj;
	char *format;
	va_dcl
#endif
{
	va_list vargs;
	object *args;
	object *res;

#ifdef HAVE_STDARG_PROTOTYPES
	va_start(vargs, format);
#else
	va_start(vargs);
#endif

	args = vmkvalue(format, vargs);
	va_end(vargs);

	if (args == NULL)
		return NULL;

	res = call_object(obj, args);
	DECREF(args);

	return res;
}


#ifdef HAVE_STDARG_PROTOTYPES
object *
441
PyEval_CallMethod(object *obj, char *methonname, char *format, ...)
442 443
#else
object *
444
PyEval_CallMethod(obj, methonname, format, va_alist)
445
	object *obj;
446
	char *methonname;
447 448 449 450 451 452 453 454 455
	char *format;
	va_dcl
#endif
{
	va_list vargs;
	object *meth;
	object *args;
	object *res;

456
	meth = getattr(obj, methonname);
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
	if (meth == NULL)
		return NULL;

#ifdef HAVE_STDARG_PROTOTYPES
	va_start(vargs, format);
#else
	va_start(vargs);
#endif

	args = vmkvalue(format, vargs);
	va_end(vargs);

	if (args == NULL) {
		DECREF(meth);
		return NULL;
	}

	res = call_object(meth, args);
	DECREF(meth);
	DECREF(args);

	return res;
479
}