From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22357 invoked by alias); 17 Mar 2011 17:25:29 -0000 Received: (qmail 22324 invoked by uid 22791); 17 Mar 2011 17:25:23 -0000 X-SWARE-Spam-Status: No, hits=-6.0 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_DB,TW_RG,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 17 Mar 2011 17:25:11 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p2HHPA2H010204 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 17 Mar 2011 13:25:10 -0400 Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p2HHP971032521 for ; Thu, 17 Mar 2011 13:25:09 -0400 From: Phil Muldoon To: gdb-patches@sourceware.org Subject: [patch] PR python/12149 (stderr output directed to stdout) Reply-to: pmuldoon@redhat.com X-URL: http://www.redhat.com Date: Thu, 17 Mar 2011 19:29:00 -0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-03/txt/msg00902.txt.bz2 This patch addresses the bug in python/12149 where output from the Python sys.stderr was being directed to stdout within GDB. In this patch I have updated gdb.write and flush to take a stream argument, and also created a new class to deal with error output. OK? Cheers, Phil -- 2011-03-17 Phil Muldoon PR python/12149 * python/python.c (gdbpy_write): Accept a stream argument and operate to the appropriate stream. (gdbpy_flush): Likewise. (_initialize_python): Add stream constants. (finish_python_initialization): Add GdbOutputErrorFile class. 2011-03-17 Phil Muldoon PR python/12149 * gdb.texinfo (Basic Python): Update gdb.write and flush text. 2011-03-17 Phil Muldoon PR python/12149 * gdb.python/python.exp: Add gdb.write tests.. -- Index: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.813 diff -u -r1.813 gdb.texinfo --- doc/gdb.texinfo 17 Mar 2011 09:36:16 -0000 1.813 +++ doc/gdb.texinfo 17 Mar 2011 17:16:06 -0000 @@ -20877,18 +20877,60 @@ @end smallexample @end defun -@findex gdb.write -@defun write string -Print a string to @value{GDBN}'s paginated standard output stream. +@findex gdb.write +@defun write string @r{[}stream{]} +Print a string to @value{GDBN}'s paginated output stream. The +optional @var{stream} determines the stream to print to. The default +stream is @value{GDBN}'s standard output stream. Possible stream +values are: + +@table @code +@findex STDOUT +@findex gdb.STDOUT +@item STDOUT +@value{GDBN}'s standard output stream. + +@findex STDERR +@findex gdb.STDERR +@item STDERR +@value{GDBN}'s error stream. + +@findex STDLOG +@findex gdb.STDLOG +@item STDLOG +@value{GDBN}'s log stream. +@end table + Writing to @code{sys.stdout} or @code{sys.stderr} will automatically -call this function. +call this function and will automatically direct the output to the +relevant stream. @end defun @findex gdb.flush @defun flush -Flush @value{GDBN}'s paginated standard output stream. Flushing -@code{sys.stdout} or @code{sys.stderr} will automatically call this -function. +Flush a @value{GDBN} paginated stream. The optional @var{stream} +determines the stream to flush. The default stream is @value{GDBN}'s +standard output stream. Possible stream values are: + +@table @code +@findex STDOUT +@findex gdb.STDOUT +@item STDOUT +@value{GDBN}'s standard output stream. + +@findex STDERR +@findex gdb.STDERR +@item STDERR +@value{GDBN}'s error stream. + +@findex STDLOG +@findex gdb.STDLOG +@item STDLOG +@value{GDBN}'s log stream. +@end table + +Flushing @code{sys.stdout} or @code{sys.stderr} will automatically +call this function for the relevant stream. @end defun @findex gdb.target_charset Index: python/python.c =================================================================== RCS file: /cvs/src/src/gdb/python/python.c,v retrieving revision 1.62 diff -u -r1.62 python.c --- python/python.c 14 Mar 2011 16:09:54 -0000 1.62 +++ python/python.c 17 Mar 2011 17:16:07 -0000 @@ -681,23 +681,69 @@ /* Printing. */ /* A python function to write a single string using gdb's filtered - output stream. */ + output stream . The optional keyword STREAM can be used to write + to a particular stream. The default stream is to gdb_stdout. */ + static PyObject * -gdbpy_write (PyObject *self, PyObject *args) +gdbpy_write (PyObject *self, PyObject *args, PyObject *kw) { char *arg; - - if (! PyArg_ParseTuple (args, "s", &arg)) + static char *keywords[] = {"text", "stream", NULL }; + int stream_type = 0; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &arg, + &stream_type)) return NULL; - printf_filtered ("%s", arg); + + switch (stream_type) + { + case 1: + { + fprintf_filtered (gdb_stderr, "%s", arg); + break; + } + case 2: + { + fprintf_filtered (gdb_stdlog, "%s", arg); + break; + } + default: + fprintf_filtered (gdb_stdout, "%s", arg); + } + Py_RETURN_NONE; } -/* A python function to flush gdb's filtered output stream. */ +/* A python function to flush a gdb stream. The optional keyword + STREAM can be used to flush a particular stream. The default stream + is gdb_stdout. */ + static PyObject * -gdbpy_flush (PyObject *self, PyObject *args) +gdbpy_flush (PyObject *self, PyObject *args, PyObject *kw) { - gdb_flush (gdb_stdout); + static char *keywords[] = {"stream", NULL }; + int stream_type = 0; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "|i", keywords, + &stream_type)) + return NULL; + + switch (stream_type) + { + case 1: + { + gdb_flush (gdb_stderr); + break; + } + case 2: + { + gdb_flush (gdb_stdlog); + break; + } + default: + gdb_flush (gdb_stdout); + } + Py_RETURN_NONE; } @@ -975,6 +1021,11 @@ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name); + /* Add stream constants. */ + PyModule_AddIntConstant (gdb_module, "STDOUT", 0); + PyModule_AddIntConstant (gdb_module, "STDERR", 1); + PyModule_AddIntConstant (gdb_module, "STDLOG", 2); + /* gdb.parameter ("data-directory") doesn't necessarily exist when the python script below is run (depending on order of _initialize_* functions). Define the initial value of gdb.PYTHONDIR here. */ @@ -1068,7 +1119,7 @@ return False\n\ \n\ def write(self, s):\n\ - gdb.write(s)\n\ + gdb.write(s, stream=gdb.STDOUT)\n \ \n\ def writelines(self, iterable):\n\ for line in iterable:\n\ @@ -1077,9 +1128,28 @@ def flush(self):\n\ gdb.flush()\n\ \n\ -sys.stderr = GdbOutputFile()\n\ sys.stdout = GdbOutputFile()\n\ \n\ +class GdbOutputErrorFile:\n\ + def close(self):\n\ + # Do nothing.\n\ + return None\n\ +\n\ + def isatty(self):\n\ + return False\n\ +\n\ + def write(self, s):\n\ + gdb.write(s, stream=gdb.STDERR)\n \ +\n\ + def writelines(self, iterable):\n\ + for line in iterable:\n\ + self.write(line)\n \ +\n\ + def flush(self):\n\ + gdb.flush()\n\ +\n\ +sys.stderr = GdbOutputErrorFile()\n\ +\n\ # Ideally this would live in the gdb module, but it's intentionally written\n\ # in python, and we need this to bootstrap the gdb module.\n\ \n\ @@ -1199,10 +1269,9 @@ Parse String and return an argv-like array.\n\ Arguments are separate by spaces and may be quoted." }, - - { "write", gdbpy_write, METH_VARARGS, + { "write", (PyCFunction)gdbpy_write, METH_VARARGS | METH_KEYWORDS, "Write a string using gdb's filtered stream." }, - { "flush", gdbpy_flush, METH_NOARGS, + { "flush", (PyCFunction)gdbpy_flush, METH_VARARGS | METH_KEYWORDS, "Flush gdb's filtered stdout stream." }, { "selected_thread", gdbpy_selected_thread, METH_NOARGS, "selected_thread () -> gdb.InferiorThread.\n\ Index: testsuite/gdb.python/python.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.python/python.exp,v retrieving revision 1.20 diff -u -r1.20 python.exp --- testsuite/gdb.python/python.exp 10 Jan 2011 11:00:24 -0000 1.20 +++ testsuite/gdb.python/python.exp 17 Mar 2011 17:16:08 -0000 @@ -170,3 +170,11 @@ gdb_test "python print len(symtab\[1\])" "1" "Test decode_line func1 length" gdb_test "python print symtab\[1\]\[0\].symtab" "gdb/testsuite/gdb.python/python-1.c.*" "Test decode_line func1 filename" gdb_test "python print symtab\[1\]\[0\].line" "19" "Test decode_line func1 line number" + +# gdb.write +gdb_test "python print sys.stderr" ".*__main__.GdbOutputErrorFile instance at.*" "Test stderr location" +gdb_test "python print sys.stdout" ".*__main__.GdbOutputFile instance at.*" "Test stdout location" +gdb_test "python gdb.write(\"Foo\\n\")" "Foo" "Test default write" +gdb_test "python gdb.write(\"Error stream\\n\", stream=gdb.STDERR)" "Error stream" "Test stderr write" +gdb_test "python gdb.write(\"Normal stream\\n\", stream=gdb.STDOUT)" "Normal stream" "Test stdout write" +gdb_test "python gdb.write(\"Log stream\\n\", stream=gdb.STDLOG)" "Log stream" "Test stdlog write"