/* APIs to write to sys.stdout or sys.stderr using a printf-like interface. Adapted from code submitted by Just van Rossum. PySys_WriteStdout(format, ...) PySys_WriteStderr(format, ...) The first function writes to sys.stdout; the second to sys.stderr. When there is a problem, they write to the real (C level) stdout or stderr; no exceptions are raised. Both take a printf-style format string as their first argument followed by a variable length argument list determined by the format string. *** WARNING *** The format should limit the total size of the formatted output string to 1000 bytes. In particular, this means that no unrestricted "%s" formats should occur; these should be limited using "%.s where is a decimal number calculated so that plus the maximum size of other formatted text does not exceed 1000 bytes. Also watch out for "%f", which can print hundreds of digits for very large numbers. */ static void mywrite(char *name, FILE *fp, const char *format, va_list va) { PyObject *file; PyObject *error_type, *error_value, *error_traceback; PyErr_Fetch(&error_type, &error_value, &error_traceback); file = PySys_GetObject(name); if (file == NULL || PyFile_AsFile(file) == fp) vfprintf(fp, format, va); else { char buffer[1001]; const int written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va); if (PyFile_WriteString(buffer, file) != 0) { PyErr_Clear(); fputs(buffer, fp); } if (written < 0 || (size_t)written >= sizeof(buffer)) { const char *truncated = "... truncated"; if (PyFile_WriteString(truncated, file) != 0) { PyErr_Clear(); fputs(truncated, fp); } } } PyErr_Restore(error_type, error_value, error_traceback); } void PySys_WriteStdout(const char *format, ...) { va_list va; va_start(va, format); mywrite("stdout", stdout, format, va); va_end(va); } void PySys_WriteStderr(const char *format, ...) { va_list va; va_start(va, format); mywrite("stderr", stderr, format, va); va_end(va); }