From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16416 invoked by alias); 14 Aug 2008 03:57:18 -0000 Received: (qmail 16398 invoked by uid 22791); 14 Aug 2008 03:57:15 -0000 X-Spam-Check-By: sourceware.org Received: from igw3.br.ibm.com (HELO igw3.br.ibm.com) (32.104.18.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 14 Aug 2008 03:56:10 +0000 Received: from mailhub3.br.ibm.com (unknown [9.18.232.110]) by igw3.br.ibm.com (Postfix) with ESMTP id 89B2439012A for ; Thu, 14 Aug 2008 00:36:15 -0300 (BRST) Received: from d24av01.br.ibm.com (d24av01.br.ibm.com [9.18.232.46]) by mailhub3.br.ibm.com (8.13.8/8.13.8/NCO v8.7) with ESMTP id m7E3tpAe938102 for ; Thu, 14 Aug 2008 00:55:56 -0300 Received: from d24av01.br.ibm.com (loopback [127.0.0.1]) by d24av01.br.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m7E3tiLq023855 for ; Thu, 14 Aug 2008 00:55:45 -0300 Received: from [9.18.201.136] ([9.18.201.136]) by d24av01.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id m7E3tipQ023694; Thu, 14 Aug 2008 00:55:44 -0300 Subject: Re: Fix python indented multi-line commands From: Thiago Jung Bauermann To: Eli Zaretskii Cc: gdb-patches@sources.redhat.com, Daniel Jacobowitz In-Reply-To: References: Content-Type: text/plain Date: Thu, 14 Aug 2008 03:57:00 -0000 Message-Id: <1218686123.8263.18.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Evolution 2.22.3.1 Content-Transfer-Encoding: 7bit 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: 2008-08/txt/msg00365.txt.bz2 Hi Eli, Thanks for the review. On Wed, 2008-08-13 at 21:21 +0300, Eli Zaretskii wrote: > > /* Read one line from the input stream. If the command is an "else" or > > - "end", return such an indication to the caller. */ > > + "end", return such an indication to the caller. If SPECIAL_PROCESSING > > + is true, strip leading and trailing whitespace in the line and attempt > > + to recognize GDB control commands. Otherwise, only "end" is > > + recognized. */ > > > > static enum misc_command_type > > -read_next_line (struct command_line **command) > > +read_next_line (struct command_line **command, int special_processing) > > Please don't call variables by mysterious names such as > "special_processing". Please give that variable a meaningful name > that would explain the purpose of this flag even without reading the > code of the callers of this function. I agree. The argument has two effects though (stripping of leading whitespace, and recognizing GDB control commands), so I had some difficulty in finding a meaningful name for it. That's why I left it with that one. It is now called parse_input, what do you think? This patch also adds the testcase asked by Daniel. I also moved the check for commented and blank lines into the parse_input if block. That's because it will otherwise change the line numbering of scripts passed to the python interpreter. This makes python error messages confusing as their line numbers won't match the user's script. Retested, introduces no regression to the testsuite. Ok? -- []'s Thiago Jung Bauermann IBM Linux Technology Center gdb/ 2008-08-13 Vladimir Prus Thiago Jung Bauermann * cli-script.c (read_next_line): Add parse_input argument. (recurse_read_control_structure): Adapt to new read_next_line signature. (read_command_lines): Add parse_input argument. (define_command): Adapt to new read_command_lines signature. (document_command): Likewise. * breakpoint.c (commands_command): Likewise. * defs.h (read_command_lines): Adjust function prototype. testsuite/ 2008-08-13 Thiago Jung Bauermann * gdb.base/define.exp: Test indented command documentation. * gdb.python/python.exp: Test indented multi-line command. Index: gdb.git/gdb/breakpoint.c =================================================================== --- gdb.git.orig/gdb/breakpoint.c 2008-08-13 23:10:26.000000000 -0300 +++ gdb.git/gdb/breakpoint.c 2008-08-13 23:10:27.000000000 -0300 @@ -675,7 +675,7 @@ commands_command (char *arg, int from_tt char *tmpbuf = xstrprintf ("Type commands for when breakpoint %d is hit, one per line.", bnum); struct cleanup *cleanups = make_cleanup (xfree, tmpbuf); - l = read_command_lines (tmpbuf, from_tty); + l = read_command_lines (tmpbuf, from_tty, 1); do_cleanups (cleanups); free_command_lines (&b->commands); b->commands = l; Index: gdb.git/gdb/cli/cli-script.c =================================================================== --- gdb.git.orig/gdb/cli/cli-script.c 2008-08-13 23:10:26.000000000 -0300 +++ gdb.git/gdb/cli/cli-script.c 2008-08-13 23:44:40.000000000 -0300 @@ -839,14 +839,19 @@ realloc_body_list (struct command_line * command->body_count = new_length; } -/* Read one line from the input stream. If the command is an "else" or - "end", return such an indication to the caller. */ +/* Read one line from the input stream. If the command is an "end", + return such an indication to the caller. If PARSE_INPUT is true, + strip leading whitespace (trailing whitespace is always stripped) + in the line, attempt to recognize GDB control commands, and also + return an indication if the command is an "else" or a nop. + Otherwise, only "end" is recognized. */ static enum misc_command_type -read_next_line (struct command_line **command) +read_next_line (struct command_line **command, int parse_input) { char *p, *p1, *prompt_ptr, control_prompt[256]; int i = 0; + int not_handled = 0; if (control_level >= 254) error (_("Control nesting too deep!")); @@ -869,81 +874,91 @@ read_next_line (struct command_line **co if (p == NULL) return end_command; - /* Strip leading and trailing whitespace. */ - while (*p == ' ' || *p == '\t') - p++; + if (parse_input) + { + /* Strip leading whitespace. */ + while (*p == ' ' || *p == '\t') + p++; + } + /* Strip trailing whitespace. */ p1 = p + strlen (p); while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t')) p1--; - /* Blanks and comments don't really do anything, but we need to - distinguish them from else, end and other commands which can be - executed. */ - if (p1 == p || p[0] == '#') - return nop_command; - /* Is this the end of a simple, while, or if control structure? */ if (p1 - p == 3 && !strncmp (p, "end", 3)) return end_command; - /* Is the else clause of an if control structure? */ - if (p1 - p == 4 && !strncmp (p, "else", 4)) - return else_command; - - /* Check for while, if, break, continue, etc and build a new command - line structure for them. */ - if (p1 - p > 5 && !strncmp (p, "while", 5)) - { - char *first_arg; - first_arg = p + 5; - while (first_arg < p1 && isspace (*first_arg)) - first_arg++; - *command = build_command_line (while_control, first_arg); - } - else if (p1 - p > 2 && !strncmp (p, "if", 2)) - { - char *first_arg; - first_arg = p + 2; - while (first_arg < p1 && isspace (*first_arg)) - first_arg++; - *command = build_command_line (if_control, first_arg); - } - else if (p1 - p >= 8 && !strncmp (p, "commands", 8)) - { - char *first_arg; - first_arg = p + 8; - while (first_arg < p1 && isspace (*first_arg)) - first_arg++; - *command = build_command_line (commands_control, first_arg); - } - else if (p1 - p == 6 && !strncmp (p, "python", 6)) - { - /* Note that we ignore the inline "python command" form - here. */ - *command = build_command_line (python_control, ""); - } - else if (p1 - p == 10 && !strncmp (p, "loop_break", 10)) - { - *command = (struct command_line *) - xmalloc (sizeof (struct command_line)); - (*command)->next = NULL; - (*command)->line = NULL; - (*command)->control_type = break_control; - (*command)->body_count = 0; - (*command)->body_list = NULL; - } - else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13)) + if (parse_input) { - *command = (struct command_line *) - xmalloc (sizeof (struct command_line)); - (*command)->next = NULL; - (*command)->line = NULL; - (*command)->control_type = continue_control; - (*command)->body_count = 0; - (*command)->body_list = NULL; + /* Blanks and comments don't really do anything, but we need to + distinguish them from else, end and other commands which can be + executed. */ + if (p1 == p || p[0] == '#') + return nop_command; + + /* Is the else clause of an if control structure? */ + if (p1 - p == 4 && !strncmp (p, "else", 4)) + return else_command; + + /* Check for while, if, break, continue, etc and build a new command + line structure for them. */ + if (p1 - p > 5 && !strncmp (p, "while", 5)) + { + char *first_arg; + first_arg = p + 5; + while (first_arg < p1 && isspace (*first_arg)) + first_arg++; + *command = build_command_line (while_control, first_arg); + } + else if (p1 - p > 2 && !strncmp (p, "if", 2)) + { + char *first_arg; + first_arg = p + 2; + while (first_arg < p1 && isspace (*first_arg)) + first_arg++; + *command = build_command_line (if_control, first_arg); + } + else if (p1 - p >= 8 && !strncmp (p, "commands", 8)) + { + char *first_arg; + first_arg = p + 8; + while (first_arg < p1 && isspace (*first_arg)) + first_arg++; + *command = build_command_line (commands_control, first_arg); + } + else if (p1 - p == 6 && !strncmp (p, "python", 6)) + { + /* Note that we ignore the inline "python command" form + here. */ + *command = build_command_line (python_control, ""); + } + else if (p1 - p == 10 && !strncmp (p, "loop_break", 10)) + { + *command = (struct command_line *) + xmalloc (sizeof (struct command_line)); + (*command)->next = NULL; + (*command)->line = NULL; + (*command)->control_type = break_control; + (*command)->body_count = 0; + (*command)->body_list = NULL; + } + else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13)) + { + *command = (struct command_line *) + xmalloc (sizeof (struct command_line)); + (*command)->next = NULL; + (*command)->line = NULL; + (*command)->control_type = continue_control; + (*command)->body_count = 0; + (*command)->body_list = NULL; + } + else + not_handled = 1; } - else + + if (!parse_input || not_handled) { /* A normal command. */ *command = (struct command_line *) @@ -989,7 +1004,7 @@ recurse_read_control_structure (struct c dont_repeat (); next = NULL; - val = read_next_line (&next); + val = read_next_line (&next, current_cmd->control_type != python_control); /* Just skip blanks and comments. */ if (val == nop_command) @@ -1071,12 +1086,16 @@ recurse_read_control_structure (struct c /* Read lines from the input stream and accumulate them in a chain of struct command_line's, which is then returned. For input from a terminal, the special command "end" is used to mark the end of the - input, and is not included in the returned chain of commands. */ + input, and is not included in the returned chain of commands. + + If PARSE_INPUT is true, strip leading whitespace (trailing whitespace + is always stripped) in the line and attempt to recognize GDB control + commands. Otherwise, only "end" is recognized. */ #define END_MESSAGE "End with a line saying just \"end\"." struct command_line * -read_command_lines (char *prompt_arg, int from_tty) +read_command_lines (char *prompt_arg, int from_tty, int parse_input) { struct command_line *head, *tail, *next; struct cleanup *old_chain; @@ -1105,7 +1124,7 @@ read_command_lines (char *prompt_arg, in while (1) { dont_repeat (); - val = read_next_line (&next); + val = read_next_line (&next, parse_input); /* Ignore blank lines or comments. */ if (val == nop_command) @@ -1339,7 +1358,7 @@ define_command (char *comname, int from_ *tem = tolower (*tem); sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname); - cmds = read_command_lines (tmpbuf, from_tty); + cmds = read_command_lines (tmpbuf, from_tty, 1); if (c && c->class == class_user) free_command_lines (&c->user_commands); @@ -1386,7 +1405,7 @@ document_command (char *comname, int fro error (_("Command \"%s\" is built-in."), comname); sprintf (tmpbuf, "Type documentation for \"%s\".", comname); - doclines = read_command_lines (tmpbuf, from_tty); + doclines = read_command_lines (tmpbuf, from_tty, 0); if (c->doc) xfree (c->doc); Index: gdb.git/gdb/defs.h =================================================================== --- gdb.git.orig/gdb/defs.h 2008-08-13 23:10:26.000000000 -0300 +++ gdb.git/gdb/defs.h 2008-08-13 23:10:27.000000000 -0300 @@ -668,7 +668,7 @@ struct command_line struct command_line **body_list; }; -extern struct command_line *read_command_lines (char *, int); +extern struct command_line *read_command_lines (char *, int, int); extern void free_command_lines (struct command_line **); Index: gdb.git/gdb/testsuite/gdb.python/python.exp =================================================================== --- gdb.git.orig/gdb/testsuite/gdb.python/python.exp 2008-08-13 23:10:26.000000000 -0300 +++ gdb.git/gdb/testsuite/gdb.python/python.exp 2008-08-13 23:10:27.000000000 -0300 @@ -64,3 +64,10 @@ gdb_py_test_multiple "show python comman "end" "" \ "end" "" \ "show user zzq" "User command zzq:.* python.*print 23.* end" + +gdb_py_test_multiple "indented multi-line python command" \ + "python" "" \ + "def foo ():" "" \ + " print 'hello, world!'" "" \ + "foo ()" "" \ + "end" "hello, world!" Index: gdb.git/gdb/testsuite/gdb.base/define.exp =================================================================== --- gdb.git.orig/gdb/testsuite/gdb.base/define.exp 2008-08-13 23:10:26.000000000 -0300 +++ gdb.git/gdb/testsuite/gdb.base/define.exp 2008-08-13 23:10:27.000000000 -0300 @@ -200,6 +200,31 @@ gdb_expect { timeout {fail "(timeout) help user command: nextwhere"} } +# Verify that the document command preserves whitespace in the beginning of the line. +# +send_gdb "document nextwhere\n" +gdb_expect { + -re "Type documentation for \"nextwhere\".\r\nEnd with a line saying just \"end\".\r\n>$"\ + {send_gdb " A next command that first shows you where you're stepping from.\nend\n" + gdb_expect { + -re "$gdb_prompt $" {} + timeout {fail "(timeout) preserve whitespace in help string"} + } + } + -re "$gdb_prompt $"\ + {fail "preserve whitespace in help string"} + timeout {fail "(timeout) preserve whitespace in help string"} +} + +send_gdb "help nextwhere\n" +gdb_expect { + -re " A next command that first shows you where you're stepping from.\r\n$gdb_prompt $"\ + {pass "preserve whitespace in help string"} + -re "$gdb_prompt $"\ + {fail "preserve whitespace in help string"} + timeout {fail "(timeout) preserve whitespace in help string"} +} + # Verify that the command parser doesn't require a space after an 'if' # command in a user defined function. #