sysmodule.c revision fd71b9e9d496caa510dec56a9b69966558d6ba5d
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5                        All Rights Reserved
6
7Copyright (c) 2000, BeOpen.com.
8Copyright (c) 1995-2000, Corporation for National Research Initiatives.
9Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
10All rights reserved.
11
12See the file "Misc/COPYRIGHT" for information on usage and
13redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14
15******************************************************************/
16
17/* System module */
18
19/*
20Various bits of information used by the interpreter are collected in
21module 'sys'.
22Function member:
23- exit(sts): raise SystemExit
24Data members:
25- stdin, stdout, stderr: standard file objects
26- modules: the table of modules (dictionary)
27- path: module search path (list of strings)
28- argv: script arguments (list of strings)
29- ps1, ps2: optional primary and secondary prompts (strings)
30*/
31
32#include "Python.h"
33
34#include "osdefs.h"
35
36#ifdef HAVE_UNISTD_H
37#include <unistd.h>
38#endif
39
40#ifdef MS_COREDLL
41extern void *PyWin_DLLhModule;
42/* A string loaded from the DLL at startup: */
43extern const char *PyWin_DLLVersionString;
44#endif
45
46PyObject *
47PySys_GetObject(name)
48	char *name;
49{
50	PyThreadState *tstate = PyThreadState_Get();
51	PyObject *sd = tstate->interp->sysdict;
52	if (sd == NULL)
53		return NULL;
54	return PyDict_GetItemString(sd, name);
55}
56
57FILE *
58PySys_GetFile(name, def)
59	char *name;
60	FILE *def;
61{
62	FILE *fp = NULL;
63	PyObject *v = PySys_GetObject(name);
64	if (v != NULL && PyFile_Check(v))
65		fp = PyFile_AsFile(v);
66	if (fp == NULL)
67		fp = def;
68	return fp;
69}
70
71int
72PySys_SetObject(name, v)
73	char *name;
74	PyObject *v;
75{
76	PyThreadState *tstate = PyThreadState_Get();
77	PyObject *sd = tstate->interp->sysdict;
78	if (v == NULL) {
79		if (PyDict_GetItemString(sd, name) == NULL)
80			return 0;
81		else
82			return PyDict_DelItemString(sd, name);
83	}
84	else
85		return PyDict_SetItemString(sd, name, v);
86}
87
88static PyObject *
89sys_exc_info(self, args)
90	PyObject *self;
91	PyObject *args;
92{
93	PyThreadState *tstate;
94	if (!PyArg_ParseTuple(args, ":exc_info"))
95		return NULL;
96	tstate = PyThreadState_Get();
97	return Py_BuildValue(
98		"(OOO)",
99		tstate->exc_type != NULL ? tstate->exc_type : Py_None,
100		tstate->exc_value != NULL ? tstate->exc_value : Py_None,
101		tstate->exc_traceback != NULL ?
102			tstate->exc_traceback : Py_None);
103}
104
105static char exc_info_doc[] =
106"exc_info() -> (type, value, traceback)\n\
107\n\
108Return information about the exception that is currently being handled.\n\
109This should be called from inside an except clause only.";
110
111static PyObject *
112sys_exit(self, args)
113	PyObject *self;
114	PyObject *args;
115{
116	/* Raise SystemExit so callers may catch it or clean up. */
117	PyErr_SetObject(PyExc_SystemExit, args);
118	return NULL;
119}
120
121static char exit_doc[] =
122"exit([status])\n\
123\n\
124Exit the interpreter by raising SystemExit(status).\n\
125If the status is omitted or None, it defaults to zero (i.e., success).\n\
126If the status numeric, it will be used as the system exit status.\n\
127If it is another kind of object, it will be printed and the system\n\
128exit status will be one (i.e., failure).";
129
130static PyObject *
131sys_getdefaultencoding(self, args)
132	PyObject *self;
133	PyObject *args;
134{
135	if (!PyArg_ParseTuple(args, ":getdefaultencoding"))
136		return NULL;
137	return PyString_FromString(PyUnicode_GetDefaultEncoding());
138}
139
140static char getdefaultencoding_doc[] =
141"getdefaultencoding() -> string\n\
142\n\
143Return the current default string encoding used by the Unicode \n\
144implementation.";
145
146static PyObject *
147sys_setdefaultencoding(self, args)
148	PyObject *self;
149	PyObject *args;
150{
151	char *encoding;
152	if (!PyArg_ParseTuple(args, "s:setdefaultencoding", &encoding))
153		return NULL;
154	if (PyUnicode_SetDefaultEncoding(encoding))
155	    	return NULL;
156	Py_INCREF(Py_None);
157	return Py_None;
158}
159
160static char setdefaultencoding_doc[] =
161"setdefaultencoding(encoding)\n\
162\n\
163Set the current default string encoding used by the Unicode implementation.";
164
165static PyObject *
166sys_settrace(self, args)
167	PyObject *self;
168	PyObject *args;
169{
170	PyThreadState *tstate = PyThreadState_Get();
171	if (args == Py_None)
172		args = NULL;
173	else
174		Py_XINCREF(args);
175	Py_XDECREF(tstate->sys_tracefunc);
176	tstate->sys_tracefunc = args;
177	Py_INCREF(Py_None);
178	return Py_None;
179}
180
181static char settrace_doc[] =
182"settrace(function)\n\
183\n\
184Set the global debug tracing function.  It will be called on each\n\
185function call.  See the debugger chapter in the library manual.";
186
187static PyObject *
188sys_setprofile(self, args)
189	PyObject *self;
190	PyObject *args;
191{
192	PyThreadState *tstate = PyThreadState_Get();
193	if (args == Py_None)
194		args = NULL;
195	else
196		Py_XINCREF(args);
197	Py_XDECREF(tstate->sys_profilefunc);
198	tstate->sys_profilefunc = args;
199	Py_INCREF(Py_None);
200	return Py_None;
201}
202
203static char setprofile_doc[] =
204"setprofile(function)\n\
205\n\
206Set the profiling function.  It will be called on each function call\n\
207and return.  See the profiler chapter in the library manual.";
208
209static PyObject *
210sys_setcheckinterval(self, args)
211	PyObject *self;
212	PyObject *args;
213{
214	PyThreadState *tstate = PyThreadState_Get();
215	if (!PyArg_ParseTuple(args, "i:setcheckinterval", &tstate->interp->checkinterval))
216		return NULL;
217	Py_INCREF(Py_None);
218	return Py_None;
219}
220
221static char setcheckinterval_doc[] =
222"setcheckinterval(n)\n\
223\n\
224Tell the Python interpreter to check for asynchronous events every\n\
225n instructions.  This also affects how often thread switches occur.";
226
227#ifdef USE_MALLOPT
228/* Link with -lmalloc (or -lmpc) on an SGI */
229#include <malloc.h>
230
231static PyObject *
232sys_mdebug(self, args)
233	PyObject *self;
234	PyObject *args;
235{
236	int flag;
237	if (!PyArg_ParseTuple(args, "i:mdebug", &flag))
238		return NULL;
239	mallopt(M_DEBUG, flag);
240	Py_INCREF(Py_None);
241	return Py_None;
242}
243#endif /* USE_MALLOPT */
244
245static PyObject *
246sys_getrefcount(self, args)
247	PyObject *self;
248	PyObject *args;
249{
250	PyObject *arg;
251	if (!PyArg_ParseTuple(args, "O:getrefcount", &arg))
252		return NULL;
253	return PyInt_FromLong(arg->ob_refcnt);
254}
255
256#ifdef Py_TRACE_REFS
257static PyObject *
258sys_gettotalrefcount(PyObject *self, PyObject *args)
259{
260	extern long _Py_RefTotal;
261	if (!PyArg_ParseTuple(args, ":gettotalrefcount"))
262		return NULL;
263	return PyInt_FromLong(_Py_RefTotal);
264}
265
266#endif /* Py_TRACE_REFS */
267
268static char getrefcount_doc[] =
269"getrefcount(object) -> integer\n\
270\n\
271Return the current reference count for the object.  This includes the\n\
272temporary reference in the argument list, so it is at least 2.";
273
274#ifdef COUNT_ALLOCS
275static PyObject *
276sys_getcounts(self, args)
277	PyObject *self, *args;
278{
279	extern PyObject *get_counts Py_PROTO((void));
280
281	if (!PyArg_ParseTuple(args, ":getcounts"))
282		return NULL;
283	return get_counts();
284}
285#endif
286
287#ifdef Py_TRACE_REFS
288/* Defined in objects.c because it uses static globals if that file */
289extern PyObject *_Py_GetObjects Py_PROTO((PyObject *, PyObject *));
290#endif
291
292#ifdef DYNAMIC_EXECUTION_PROFILE
293/* Defined in ceval.c because it uses static globals if that file */
294extern PyObject *_Py_GetDXProfile Py_PROTO((PyObject *,  PyObject *));
295#endif
296
297static PyMethodDef sys_methods[] = {
298	/* Might as well keep this in alphabetic order */
299	{"exc_info",	sys_exc_info, 1, exc_info_doc},
300	{"exit",	sys_exit, 0, exit_doc},
301	{"getdefaultencoding", sys_getdefaultencoding, 1, getdefaultencoding_doc},
302#ifdef COUNT_ALLOCS
303	{"getcounts",	sys_getcounts, 1},
304#endif
305#ifdef DYNAMIC_EXECUTION_PROFILE
306	{"getdxp",	_Py_GetDXProfile, 1},
307#endif
308#ifdef Py_TRACE_REFS
309	{"getobjects",	_Py_GetObjects, 1},
310	{"gettotalrefcount", sys_gettotalrefcount, 1},
311#endif
312	{"getrefcount",	sys_getrefcount, 1, getrefcount_doc},
313#ifdef USE_MALLOPT
314	{"mdebug",	sys_mdebug, 1},
315#endif
316	{"setdefaultencoding", sys_setdefaultencoding, 1, setdefaultencoding_doc},
317	{"setcheckinterval",	sys_setcheckinterval, 1, setcheckinterval_doc},
318	{"setprofile",	sys_setprofile, 0, setprofile_doc},
319	{"settrace",	sys_settrace, 0, settrace_doc},
320	{NULL,		NULL}		/* sentinel */
321};
322
323static PyObject *
324list_builtin_module_names()
325{
326	PyObject *list = PyList_New(0);
327	int i;
328	if (list == NULL)
329		return NULL;
330	for (i = 0; PyImport_Inittab[i].name != NULL; i++) {
331		PyObject *name = PyString_FromString(
332			PyImport_Inittab[i].name);
333		if (name == NULL)
334			break;
335		PyList_Append(list, name);
336		Py_DECREF(name);
337	}
338	if (PyList_Sort(list) != 0) {
339		Py_DECREF(list);
340		list = NULL;
341	}
342	if (list) {
343		PyObject *v = PyList_AsTuple(list);
344		Py_DECREF(list);
345		list = v;
346	}
347	return list;
348}
349
350/* XXX This doc string is too long to be a single string literal in VC++ 5.0.
351   Two literals concatenated works just fine.  If you have a K&R compiler
352   or other abomination that however *does* understand longer strings,
353   get rid of the !!! comment in the middle and the quotes that surround it. */
354static char sys_doc[] =
355"This module provides access to some objects used or maintained by the\n\
356interpreter and to functions that interact strongly with the interpreter.\n\
357\n\
358Dynamic objects:\n\
359\n\
360argv -- command line arguments; argv[0] is the script pathname if known\n\
361path -- module search path; path[0] is the script directory, else ''\n\
362modules -- dictionary of loaded modules\n\
363exitfunc -- you may set this to a function to be called when Python exits\n\
364\n\
365stdin -- standard input file object; used by raw_input() and input()\n\
366stdout -- standard output file object; used by the print statement\n\
367stderr -- standard error object; used for error messages\n\
368  By assigning another file object (or an object that behaves like a file)\n\
369  to one of these, it is possible to redirect all of the interpreter's I/O.\n\
370\n\
371last_type -- type of last uncaught exception\n\
372last_value -- value of last uncaught exception\n\
373last_traceback -- traceback of last uncaught exception\n\
374  These three are only available in an interactive session after a\n\
375  traceback has been printed.\n\
376\n\
377exc_type -- type of exception currently being handled\n\
378exc_value -- value of exception currently being handled\n\
379exc_traceback -- traceback of exception currently being handled\n\
380  The function exc_info() should be used instead of these three,\n\
381  because it is thread-safe.\n\
382"
383#ifndef MS_WIN16
384/* Concatenating string here */
385"\n\
386Static objects:\n\
387\n\
388maxint -- the largest supported integer (the smallest is -maxint-1)\n\
389builtin_module_names -- tuple of module names built into this intepreter\n\
390version -- the version of this interpreter as a string\n\
391version_info -- version information as a tuple\n\
392hexversion -- version information encoded as a single integer\n\
393copyright -- copyright notice pertaining to this interpreter\n\
394platform -- platform identifier\n\
395executable -- pathname of this Python interpreter\n\
396prefix -- prefix used to find the Python library\n\
397exec_prefix -- prefix used to find the machine-specific Python library\n\
398dllhandle -- [Windows only] integer handle of the Python DLL\n\
399winver -- [Windows only] version number of the Python DLL\n\
400__stdin__ -- the original stdin; don't use!\n\
401__stdout__ -- the original stdout; don't use!\n\
402__stderr__ -- the original stderr; don't use!\n\
403\n\
404Functions:\n\
405\n\
406exc_info() -- return thread-safe information about the current exception\n\
407exit() -- exit the interpreter by raising SystemExit\n\
408getrefcount() -- return the reference count for an object (plus one :-)\n\
409setcheckinterval() -- control how often the interpreter checks for events\n\
410setprofile() -- set the global profiling function\n\
411settrace() -- set the global debug tracing function\n\
412";
413#endif
414
415PyObject *
416_PySys_Init()
417{
418	extern int fclose Py_PROTO((FILE *));
419	PyObject *m, *v, *sysdict;
420	PyObject *sysin, *sysout, *syserr;
421	char *s;
422
423	m = Py_InitModule3("sys", sys_methods, sys_doc);
424	sysdict = PyModule_GetDict(m);
425
426	sysin = PyFile_FromFile(stdin, "<stdin>", "r", NULL);
427	sysout = PyFile_FromFile(stdout, "<stdout>", "w", NULL);
428	syserr = PyFile_FromFile(stderr, "<stderr>", "w", NULL);
429	if (PyErr_Occurred())
430		return NULL;
431	PyDict_SetItemString(sysdict, "stdin", sysin);
432	PyDict_SetItemString(sysdict, "stdout", sysout);
433	PyDict_SetItemString(sysdict, "stderr", syserr);
434	/* Make backup copies for cleanup */
435	PyDict_SetItemString(sysdict, "__stdin__", sysin);
436	PyDict_SetItemString(sysdict, "__stdout__", sysout);
437	PyDict_SetItemString(sysdict, "__stderr__", syserr);
438	Py_XDECREF(sysin);
439	Py_XDECREF(sysout);
440	Py_XDECREF(syserr);
441	PyDict_SetItemString(sysdict, "version",
442			     v = PyString_FromString(Py_GetVersion()));
443	Py_XDECREF(v);
444	PyDict_SetItemString(sysdict, "hexversion",
445			     v = PyInt_FromLong(PY_VERSION_HEX));
446	Py_XDECREF(v);
447	/*
448	 * These release level checks are mutually exclusive and cover
449	 * the field, so don't get too fancy with the pre-processor!
450	 */
451#if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA
452	s = "alpha";
453#endif
454#if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA
455	s = "beta";
456#endif
457#if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA
458	s = "candidate";
459#endif
460#if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL
461	s = "final";
462#endif
463	PyDict_SetItemString(sysdict, "version_info",
464			     v = Py_BuildValue("iiisi", PY_MAJOR_VERSION,
465					       PY_MINOR_VERSION,
466					       PY_MICRO_VERSION, s,
467					       PY_RELEASE_SERIAL));
468	Py_XDECREF(v);
469	PyDict_SetItemString(sysdict, "copyright",
470			     v = PyString_FromString(Py_GetCopyright()));
471	Py_XDECREF(v);
472	PyDict_SetItemString(sysdict, "platform",
473			     v = PyString_FromString(Py_GetPlatform()));
474	Py_XDECREF(v);
475	PyDict_SetItemString(sysdict, "executable",
476			     v = PyString_FromString(Py_GetProgramFullPath()));
477	Py_XDECREF(v);
478	PyDict_SetItemString(sysdict, "prefix",
479			     v = PyString_FromString(Py_GetPrefix()));
480	Py_XDECREF(v);
481	PyDict_SetItemString(sysdict, "exec_prefix",
482		   v = PyString_FromString(Py_GetExecPrefix()));
483	Py_XDECREF(v);
484	PyDict_SetItemString(sysdict, "maxint",
485			     v = PyInt_FromLong(PyInt_GetMax()));
486	Py_XDECREF(v);
487	PyDict_SetItemString(sysdict, "builtin_module_names",
488		   v = list_builtin_module_names());
489	Py_XDECREF(v);
490#ifdef MS_COREDLL
491	PyDict_SetItemString(sysdict, "dllhandle",
492			     v = PyLong_FromVoidPtr(PyWin_DLLhModule));
493	Py_XDECREF(v);
494	PyDict_SetItemString(sysdict, "winver",
495			     v = PyString_FromString(PyWin_DLLVersionString));
496	Py_XDECREF(v);
497#endif
498	if (PyErr_Occurred())
499		return NULL;
500	return m;
501}
502
503static PyObject *
504makepathobject(path, delim)
505	char *path;
506	int delim;
507{
508	int i, n;
509	char *p;
510	PyObject *v, *w;
511
512	n = 1;
513	p = path;
514	while ((p = strchr(p, delim)) != NULL) {
515		n++;
516		p++;
517	}
518	v = PyList_New(n);
519	if (v == NULL)
520		return NULL;
521	for (i = 0; ; i++) {
522		p = strchr(path, delim);
523		if (p == NULL)
524			p = strchr(path, '\0'); /* End of string */
525		w = PyString_FromStringAndSize(path, (int) (p - path));
526		if (w == NULL) {
527			Py_DECREF(v);
528			return NULL;
529		}
530		PyList_SetItem(v, i, w);
531		if (*p == '\0')
532			break;
533		path = p+1;
534	}
535	return v;
536}
537
538void
539PySys_SetPath(path)
540	char *path;
541{
542	PyObject *v;
543	if ((v = makepathobject(path, DELIM)) == NULL)
544		Py_FatalError("can't create sys.path");
545	if (PySys_SetObject("path", v) != 0)
546		Py_FatalError("can't assign sys.path");
547	Py_DECREF(v);
548}
549
550static PyObject *
551makeargvobject(argc, argv)
552	int argc;
553	char **argv;
554{
555	PyObject *av;
556	if (argc <= 0 || argv == NULL) {
557		/* Ensure at least one (empty) argument is seen */
558		static char *empty_argv[1] = {""};
559		argv = empty_argv;
560		argc = 1;
561	}
562	av = PyList_New(argc);
563	if (av != NULL) {
564		int i;
565		for (i = 0; i < argc; i++) {
566			PyObject *v = PyString_FromString(argv[i]);
567			if (v == NULL) {
568				Py_DECREF(av);
569				av = NULL;
570				break;
571			}
572			PyList_SetItem(av, i, v);
573		}
574	}
575	return av;
576}
577
578void
579PySys_SetArgv(argc, argv)
580	int argc;
581	char **argv;
582{
583	PyObject *av = makeargvobject(argc, argv);
584	PyObject *path = PySys_GetObject("path");
585	if (av == NULL)
586		Py_FatalError("no mem for sys.argv");
587	if (PySys_SetObject("argv", av) != 0)
588		Py_FatalError("can't assign sys.argv");
589	if (path != NULL) {
590		char *argv0 = argv[0];
591		char *p = NULL;
592		int n = 0;
593		PyObject *a;
594#ifdef HAVE_READLINK
595		char link[MAXPATHLEN+1];
596		char argv0copy[2*MAXPATHLEN+1];
597		int nr = 0;
598		if (argc > 0 && argv0 != NULL)
599			nr = readlink(argv0, link, MAXPATHLEN);
600		if (nr > 0) {
601			/* It's a symlink */
602			link[nr] = '\0';
603			if (link[0] == SEP)
604				argv0 = link; /* Link to absolute path */
605			else if (strchr(link, SEP) == NULL)
606				; /* Link without path */
607			else {
608				/* Must join(dirname(argv0), link) */
609				char *q = strrchr(argv0, SEP);
610				if (q == NULL)
611					argv0 = link; /* argv0 without path */
612				else {
613					/* Must make a copy */
614					strcpy(argv0copy, argv0);
615					q = strrchr(argv0copy, SEP);
616					strcpy(q+1, link);
617					argv0 = argv0copy;
618				}
619			}
620		}
621#endif /* HAVE_READLINK */
622#if SEP == '\\' /* Special case for MS filename syntax */
623		if (argc > 0 && argv0 != NULL) {
624			char *q;
625			p = strrchr(argv0, SEP);
626			/* Test for alternate separator */
627			q = strrchr(p ? p : argv0, '/');
628			if (q != NULL)
629				p = q;
630			if (p != NULL) {
631				n = p + 1 - argv0;
632				if (n > 1 && p[-1] != ':')
633					n--; /* Drop trailing separator */
634			}
635		}
636#else /* All other filename syntaxes */
637		if (argc > 0 && argv0 != NULL)
638			p = strrchr(argv0, SEP);
639		if (p != NULL) {
640			n = p + 1 - argv0;
641#if SEP == '/' /* Special case for Unix filename syntax */
642			if (n > 1)
643				n--; /* Drop trailing separator */
644#endif /* Unix */
645		}
646#endif /* All others */
647		a = PyString_FromStringAndSize(argv0, n);
648		if (a == NULL)
649			Py_FatalError("no mem for sys.path insertion");
650		if (PyList_Insert(path, 0, a) < 0)
651			Py_FatalError("sys.path.insert(0) failed");
652		Py_DECREF(a);
653	}
654	Py_DECREF(av);
655}
656
657
658/* APIs to write to sys.stdout or sys.stderr using a printf-like interface.
659   Adapted from code submitted by Just van Rossum.
660
661   PySys_WriteStdout(format, ...)
662   PySys_WriteStderr(format, ...)
663
664      The first function writes to sys.stdout; the second to sys.stderr.  When
665      there is a problem, they write to the real (C level) stdout or stderr;
666      no exceptions are raised.
667
668      Both take a printf-style format string as their first argument followed
669      by a variable length argument list determined by the format string.
670
671      *** WARNING ***
672
673      The format should limit the total size of the formatted output string to
674      1000 bytes.  In particular, this means that no unrestricted "%s" formats
675      should occur; these should be limited using "%.<N>s where <N> is a
676      decimal number calculated so that <N> plus the maximum size of other
677      formatted text does not exceed 1000 bytes.  Also watch out for "%f",
678      which can print hundreds of digits for very large numbers.
679
680 */
681
682static void
683mywrite(name, fp, format, va)
684	char *name;
685	FILE *fp;
686	const char *format;
687	va_list va;
688{
689	PyObject *file;
690	PyObject *error_type, *error_value, *error_traceback;
691
692	PyErr_Fetch(&error_type, &error_value, &error_traceback);
693	file = PySys_GetObject(name);
694	if (file == NULL || PyFile_AsFile(file) == fp)
695		vfprintf(fp, format, va);
696	else {
697		char buffer[1001];
698		if (vsprintf(buffer, format, va) >= sizeof(buffer))
699		    Py_FatalError("PySys_WriteStdout/err: buffer overrun");
700		if (PyFile_WriteString(buffer, file) != 0) {
701			PyErr_Clear();
702			fputs(buffer, fp);
703		}
704	}
705	PyErr_Restore(error_type, error_value, error_traceback);
706}
707
708void
709#ifdef HAVE_STDARG_PROTOTYPES
710PySys_WriteStdout(const char *format, ...)
711#else
712PySys_WriteStdout(va_alist)
713	va_dcl
714#endif
715{
716	va_list va;
717
718#ifdef HAVE_STDARG_PROTOTYPES
719	va_start(va, format);
720#else
721	char *format;
722	va_start(va);
723	format = va_arg(va, char *);
724#endif
725	mywrite("stdout", stdout, format, va);
726	va_end(va);
727}
728
729void
730#ifdef HAVE_STDARG_PROTOTYPES
731PySys_WriteStderr(const char *format, ...)
732#else
733PySys_WriteStderr(va_alist)
734	va_dcl
735#endif
736{
737	va_list va;
738
739#ifdef HAVE_STDARG_PROTOTYPES
740	va_start(va, format);
741#else
742	char *format;
743	va_start(va);
744	format = va_arg(va, char *);
745#endif
746	mywrite("stderr", stderr, format, va);
747	va_end(va);
748}
749