198944Sobrien/* MI Command Set - MI parser. 2130803Smarcel 3130803Smarcel Copyright 2000, 2001, 2002 Free Software Foundation, Inc. 4130803Smarcel 598944Sobrien Contributed by Cygnus Solutions (a Red Hat company). 698944Sobrien 798944Sobrien This file is part of GDB. 898944Sobrien 998944Sobrien This program is free software; you can redistribute it and/or modify 1098944Sobrien it under the terms of the GNU General Public License as published by 1198944Sobrien the Free Software Foundation; either version 2 of the License, or 1298944Sobrien (at your option) any later version. 1398944Sobrien 1498944Sobrien This program is distributed in the hope that it will be useful, 1598944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1698944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1798944Sobrien GNU General Public License for more details. 1898944Sobrien 1998944Sobrien You should have received a copy of the GNU General Public License 2098944Sobrien along with this program; if not, write to the Free Software 2198944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2298944Sobrien Boston, MA 02111-1307, USA. */ 2398944Sobrien 2498944Sobrien#include "defs.h" 2598944Sobrien#include "mi-cmds.h" 2698944Sobrien#include "mi-parse.h" 2798944Sobrien 2898944Sobrien#include <ctype.h> 2998944Sobrien#include "gdb_string.h" 3098944Sobrien 3198944Sobrienstatic void 3298944Sobrienmi_parse_argv (char *args, struct mi_parse *parse) 3398944Sobrien{ 3498944Sobrien char *chp = args; 3598944Sobrien int argc = 0; 3698944Sobrien char **argv = xmalloc ((argc + 1) * sizeof (char *)); 3798944Sobrien argv[argc] = NULL; 3898944Sobrien while (1) 3998944Sobrien { 4098944Sobrien char *arg; 4198944Sobrien /* skip leading white space */ 4298944Sobrien while (isspace (*chp)) 4398944Sobrien chp++; 4498944Sobrien /* Three possibilities: EOF, quoted string, or other text. */ 4598944Sobrien switch (*chp) 4698944Sobrien { 4798944Sobrien case '\0': 4898944Sobrien parse->argv = argv; 4998944Sobrien parse->argc = argc; 5098944Sobrien return; 5198944Sobrien case '"': 5298944Sobrien { 5398944Sobrien /* A quoted string. */ 5498944Sobrien int len; 5598944Sobrien char *start = chp + 1; 5698944Sobrien /* Determine the buffer size. */ 5798944Sobrien chp = start; 5898944Sobrien len = 0; 5998944Sobrien while (*chp != '\0' && *chp != '"') 6098944Sobrien { 6198944Sobrien if (*chp == '\\') 6298944Sobrien { 6398944Sobrien chp++; 6498944Sobrien if (parse_escape (&chp) <= 0) 6598944Sobrien { 6698944Sobrien /* Do not allow split lines or "\000" */ 6798944Sobrien freeargv (argv); 6898944Sobrien return; 6998944Sobrien } 7098944Sobrien } 7198944Sobrien else 7298944Sobrien chp++; 7398944Sobrien len++; 7498944Sobrien } 7598944Sobrien /* Insist on a closing quote. */ 7698944Sobrien if (*chp != '"') 7798944Sobrien { 7898944Sobrien freeargv (argv); 7998944Sobrien return; 8098944Sobrien } 8198944Sobrien /* Insist on trailing white space. */ 8298944Sobrien if (chp[1] != '\0' && !isspace (chp[1])) 8398944Sobrien { 8498944Sobrien freeargv (argv); 8598944Sobrien return; 8698944Sobrien } 8798944Sobrien /* create the buffer. */ 8898944Sobrien arg = xmalloc ((len + 1) * sizeof (char)); 8998944Sobrien /* And copy the characters in. */ 9098944Sobrien chp = start; 9198944Sobrien len = 0; 9298944Sobrien while (*chp != '\0' && *chp != '"') 9398944Sobrien { 9498944Sobrien if (*chp == '\\') 9598944Sobrien { 9698944Sobrien chp++; 9798944Sobrien arg[len] = parse_escape (&chp); 9898944Sobrien } 9998944Sobrien else 10098944Sobrien arg[len] = *chp++; 10198944Sobrien len++; 10298944Sobrien } 10398944Sobrien arg[len] = '\0'; 10498944Sobrien chp++; /* that closing quote. */ 10598944Sobrien break; 10698944Sobrien } 10798944Sobrien default: 10898944Sobrien { 10998944Sobrien /* An unquoted string. Accumulate all non blank 11098944Sobrien characters into a buffer. */ 11198944Sobrien int len; 11298944Sobrien char *start = chp; 11398944Sobrien while (*chp != '\0' && !isspace (*chp)) 11498944Sobrien { 11598944Sobrien chp++; 11698944Sobrien } 11798944Sobrien len = chp - start; 11898944Sobrien arg = xmalloc ((len + 1) * sizeof (char)); 11998944Sobrien strncpy (arg, start, len); 12098944Sobrien arg[len] = '\0'; 12198944Sobrien break; 12298944Sobrien } 12398944Sobrien } 12498944Sobrien /* Append arg to argv. */ 12598944Sobrien argv = xrealloc (argv, (argc + 2) * sizeof (char *)); 12698944Sobrien argv[argc++] = arg; 12798944Sobrien argv[argc] = NULL; 12898944Sobrien } 12998944Sobrien} 13098944Sobrien 13198944Sobrien 13298944Sobrienvoid 13398944Sobrienmi_parse_free (struct mi_parse *parse) 13498944Sobrien{ 13598944Sobrien if (parse == NULL) 13698944Sobrien return; 13798944Sobrien if (parse->command != NULL) 13898944Sobrien xfree (parse->command); 13998944Sobrien if (parse->token != NULL) 14098944Sobrien xfree (parse->token); 14198944Sobrien if (parse->args != NULL) 14298944Sobrien xfree (parse->args); 14398944Sobrien if (parse->argv != NULL) 14498944Sobrien freeargv (parse->argv); 14598944Sobrien xfree (parse); 14698944Sobrien} 14798944Sobrien 14898944Sobrien 14998944Sobrienstruct mi_parse * 15098944Sobrienmi_parse (char *cmd) 15198944Sobrien{ 15298944Sobrien char *chp; 15398944Sobrien struct mi_parse *parse = XMALLOC (struct mi_parse); 15498944Sobrien memset (parse, 0, sizeof (*parse)); 15598944Sobrien 15698944Sobrien /* Before starting, skip leading white space. */ 15798944Sobrien while (isspace (*cmd)) 15898944Sobrien cmd++; 15998944Sobrien 16098944Sobrien /* Find/skip any token and then extract it. */ 16198944Sobrien for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++) 16298944Sobrien ; 16398944Sobrien parse->token = xmalloc ((chp - cmd + 1) * sizeof (char *)); 16498944Sobrien memcpy (parse->token, cmd, (chp - cmd)); 16598944Sobrien parse->token[chp - cmd] = '\0'; 16698944Sobrien 16798944Sobrien /* This wasn't a real MI command. Return it as a CLI_COMMAND. */ 16898944Sobrien if (*chp != '-') 16998944Sobrien { 17098944Sobrien while (isspace (*chp)) 17198944Sobrien chp++; 17298944Sobrien parse->command = xstrdup (chp); 17398944Sobrien parse->op = CLI_COMMAND; 17498944Sobrien return parse; 17598944Sobrien } 17698944Sobrien 17798944Sobrien /* Extract the command. */ 17898944Sobrien { 17998944Sobrien char *tmp = chp + 1; /* discard ``-'' */ 18098944Sobrien for (; *chp && !isspace (*chp); chp++) 18198944Sobrien ; 18298944Sobrien parse->command = xmalloc ((chp - tmp + 1) * sizeof (char *)); 18398944Sobrien memcpy (parse->command, tmp, chp - tmp); 18498944Sobrien parse->command[chp - tmp] = '\0'; 18598944Sobrien } 18698944Sobrien 18798944Sobrien /* Find the command in the MI table. */ 18898944Sobrien parse->cmd = mi_lookup (parse->command); 18998944Sobrien if (parse->cmd == NULL) 19098944Sobrien { 19198944Sobrien /* FIXME: This should be a function call. */ 19298944Sobrien fprintf_unfiltered 19398944Sobrien (raw_stdout, 19498944Sobrien "%s^error,msg=\"Undefined MI command: %s\"\n", 19598944Sobrien parse->token, parse->command); 19698944Sobrien mi_parse_free (parse); 19798944Sobrien return NULL; 19898944Sobrien } 19998944Sobrien 20098944Sobrien /* Skip white space following the command. */ 20198944Sobrien while (isspace (*chp)) 20298944Sobrien chp++; 20398944Sobrien 20498944Sobrien /* For new argv commands, attempt to return the parsed argument 20598944Sobrien list. */ 20698944Sobrien if (parse->cmd->argv_func != NULL) 20798944Sobrien { 20898944Sobrien mi_parse_argv (chp, parse); 20998944Sobrien if (parse->argv == NULL) 21098944Sobrien { 21198944Sobrien /* FIXME: This should be a function call. */ 21298944Sobrien fprintf_unfiltered 21398944Sobrien (raw_stdout, 21498944Sobrien "%s^error,msg=\"Problem parsing arguments: %s %s\"\n", 21598944Sobrien parse->token, parse->command, chp); 21698944Sobrien mi_parse_free (parse); 21798944Sobrien return NULL; 21898944Sobrien } 21998944Sobrien } 22098944Sobrien 22198944Sobrien /* FIXME: DELETE THIS */ 22298944Sobrien /* For CLI and old ARGS commands, also return the remainder of the 22398944Sobrien command line as a single string. */ 22498944Sobrien if (parse->cmd->args_func != NULL 225130803Smarcel || parse->cmd->cli.cmd != NULL) 22698944Sobrien { 22798944Sobrien parse->args = xstrdup (chp); 22898944Sobrien } 22998944Sobrien 23098944Sobrien /* Fully parsed. */ 23198944Sobrien parse->op = MI_COMMAND; 23298944Sobrien return parse; 23398944Sobrien} 234