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