This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: small enhancements to gdb here..



Ugh!!  That is too much work.  If you will not accept this email as agreement to transfer copyright control over to FSF, then forget it.  I am not going through all that hastle just to submit a few very minor enhancements.

I gave you the patch already.  It is yours to do freely as you wish.  I do NOT retain any copyright to it, nor does my company, since it only exists on my workstation and I am the only person who knows about it and using it.

If these enhancements should appear in the next release of gdb, I will be able to delete the patch & sources from my system.

I really hope this email is enough for you to accept such a small patch.  If it is not, that's too bad...

-Don

---- Forwarded Message ----

Sender: fnasser@cygnus.com
Date: Wed, 22 Nov 2000 13:04:38 -0500
From: Fernando Nasser <fnasser@cygnus.com>
MIME-Version: 1.0
To: Don Beusee <Don.Beusee@oracle.com>
CC: gdb-patches@sourceware.cygnus.com
Subject: Re: small enhancements to gdb here..


Don,

Before we even start to talk about this you must fill up an assignment form to the
FSF and send them for processing.  This will make your changes available for inclusion
on FSF GPLed software like gdb.

Look at the CONTRIBUTE link of the GDB web page at sources.redhat.com

The FSF assignment format is at:

   http://gcc.gnu.org/fsf-forms/assignment-instructions.html

Thanks,
Fernando



Don Beusee wrote:
> 
> Hi,
> 
> I originally sent this email to gnu-gdb@gnu.org before I saw the CONTRIBUTE file.  I reformatted the diff output to your specifications.  The diff's are based on 5.0 distribution at GNU's ftp site.
> 
> I have patches for 3 small enhancements to improve convenience:
> 
> - allow O/S commands directly from gdb when no match for internal command.
> - additional arg syntax in user-defined commands:
>     $#        number of args
>     $*        all args
>     $N        specific arg (where N is a number from 1 to 9).  $1 is the first
>               arg (same as $arg0).
>     ${NN}     NN can be any number between 1 and MAXUSERARGS (10 currently).
>     ${ENV}    environment variable
> - a user command referencing an argument not provided on the command returns
>   an empty string, not an error.
> 
> Example .gdbinit:
> define sh
>    shell $*
> end
> define host
>    shell $*
> end
> define pa
>    echo args = $*, count = $#\n
>    echo arg1 = $1\n
>    echo arg2 = $2\n
>    echo arg10 = ${10}\n
>    echo arg0=$arg0\n
>    echo arg1=$arg1\n
> end
> define c
>    if strcmp("$1", "at") == 0
>       printf "continuing at %d\n", $2
>       jump $2
>    else
>       continue $*
>    end
> end
> 
> ChangeLog entry:
> 
> 2000-11-20  Don Beusee     <Don.Beusee@oracle.com>
> 
>         * gdb/command.c, gdb/top.c: If a command entered in gdb is not
>         internal, execute as a shell command.
> 
>         * gdb/top.c: Enhance user-defined command argument parsing to accept
>         $# (number of args), $* (all args), $N (where N is a number from 1 to
>         9), ${NN} where NN is any number from 1 to MAXUSERARGS (10 currently),
>         and ${ENV} where ENV is an environment variable.
> 
>         * gdb/doc/gdb.info-9: document above arg parsing in user-defined
>         commands.
> 
> Here are the patches in rcsdiff -up format:
> 
> $ rcsdiff -up gdb/command.c
> --- 1.1 2000/11/20 11:49:09
> +++ gdb/command.c       2000/11/20 11:53:35
> @@ -43,7 +43,7 @@ static void show_user_1 (struct cmd_list
> 
>  static void make_command PARAMS ((char *, int));
> 
> -static void shell_escape PARAMS ((char *, int));
> +void shell_escape PARAMS ((char *, int));
> 
>  static int parse_binary_operation PARAMS ((char *));
> 
> @@ -512,7 +512,7 @@ help_cmd (command, stream)
> 
>    c = lookup_cmd (&command, cmdlist, "", 0, 0);
> 
> -  if (c == 0)
> +  if (c == 0 || c == -1 || c == -2)
>      return;
> 
>    /* There are three cases here.
> @@ -901,8 +901,8 @@ undef_cmd_error (cmdtype, q)
>     LIST is a chain of struct cmd_list_element's.
>     If it is found, return the struct cmd_list_element for that command
>     and update *LINE to point after the command name, at the first argument.
> -   If not found, call error if ALLOW_UNKNOWN is zero
> -   otherwise (or if error returns) return zero.
> +   If not found, return -2 to signal caller to run shell if ALLOW_UNKNOWN is
> +   zero otherwise (or if error returns) return zero.
>     Call error if specified command is ambiguous,
>     unless ALLOW_UNKNOWN is negative.
>     CMDTYPE precedes the word "command" in the error message.
> @@ -948,7 +948,10 @@ lookup_cmd (line, list, cmdtype, allow_u
>               q = (char *) alloca (p - *line + 1);
>               strncpy (q, *line, p - *line);
>               q[p - *line] = '\0';
> -             undef_cmd_error (cmdtype, q);
> +             if (!*cmdtype)
> +                 return (struct cmd_list_element *) -2; /* invoke shell */
> +              else
> +                 undef_cmd_error (cmdtype, q);
>             }
>         }
>        else
> @@ -1861,7 +1864,7 @@ cmd_show_list (list, from_tty, prefix)
>  }
> 
>  /* ARGSUSED */
> -static void
> +void
>  shell_escape (arg, from_tty)
>       char *arg;
>       int from_tty;
> 
> $ rcsdiff -up gdb/top.c
> --- 1.1 2000/11/20 11:49:13
> +++ gdb/top.c   2000/11/20 12:02:39
> @@ -97,7 +97,9 @@ recurse_read_control_structure PARAMS ((
> 
>  static struct cleanup *setup_user_args PARAMS ((char *));
> 
> -static char *locate_arg PARAMS ((char *));
> +static char *locate_arg PARAMS ((char *, int *, char **, char **, char *));
> +
> +static char *itoa PARAMS ((int));
> 
>  static char *insert_args PARAMS ((char *));
> 
> @@ -144,6 +146,8 @@ static void complete_command PARAMS ((ch
> 
>  static void do_nothing PARAMS ((int));
> 
> +extern void shell_escape PARAMS ((char *, int));
> +
>  static void show_debug PARAMS ((char *, int));
> 
>  static void set_debug PARAMS ((char *, int));
> @@ -360,6 +364,7 @@ struct user_args
>         int len;
>        }
>      a[MAXUSERARGS];
> +    char args[256];
>      int count;
>    }
>   *user_args;
> @@ -1296,6 +1301,8 @@ setup_user_args (p)
>    if (p == NULL)
>      return old_chain;
> 
> +  strcpy(args->args, p);
> +
>    while (*p)
>      {
>        char *start_arg;
> @@ -1357,20 +1364,87 @@ setup_user_args (p)
>    return old_chain;
>  }
> 
> -/* Given character string P, return a point to the first argument ($arg),
> -   or NULL if P contains no arguments.  */
> +/*
> + * Given character string P, return a point to the substitution argument
> + * or variable; or NULL if P contains no arguments or variable tokens.
> + * num will contain one of the following values:
> + *    -1 (all arguments should replace this token)
> + *    -2 (argument count should replace this token)
> + *    -3 (string stored in newstr should replace this token)
> + *    the argument number,
> + */
> 
>  static char *
> -locate_arg (p)
> -     char *p;
> +locate_arg (p, num, start, after, newstr)
> +     char *p, **start, **after, *newstr;
> +     int *num;
>  {
> +  *start = NULL;
> +  *newstr = '\0';
>    while ((p = strchr (p, '$')))
>      {
>        if (strncmp (p, "$arg", 4) == 0 && isdigit (p[4]))
> -       return p;
> +       {
> +         *num = p[4]-'0';
> +         *start = p;
> +         *after = p+5;
> +         return *start;
> +       }
> +      if (p[0] == '$' && isdigit (p[1]))
> +       {
> +         *num = p[1] - '0' - 1;
> +         *start = p;
> +         *after = p+2;
> +         return *start;
> +       }
> +      if (p[0] == '$' && p[1] == '#')
> +       {
> +         *num = -2; /* indicates to replace with count */
> +         *start = p;
> +         *after = p+2;
> +         return *start;
> +       }
> +      if (p[0] == '$' && p[1] == '*')
> +       {
> +         *num = -1; /* indicates to use all args */
> +         *start = p;
> +         *after = p+2;
> +         return *start;
> +       }
> +      if (p[0] == '$' && p[1] == '{' && isdigit(p[2]))
> +       {
> +         *num = atoi(p+2) - 1;
> +         *start = p;
> +         *after = strchr(p, '}')+1;
> +         return *start;
> +       }
> +      if (p[0] == '$' && p[1] == '{')
> +        {
> +          char env[256], *e;
> +          memset(env, '\0', sizeof(env));
> +          *num = -3; /* environment variable */
> +          *start = p;
> +          *after = strchr(p, '}')+1;
> +          memcpy(env, p+2, (*after) - p - 3);
> +          if (e = getenv(env))
> +            {
> +              strcpy(newstr, e);
> +            }
> +          return *start;
> +        }
>        p++;
>      }
> -  return NULL;
> +  return *start;
> +}
> +
> +static char *
> +itoa(i)
> +        int i;
> +{
> +        static char a[12];
> +        *a = '\0';
> +        sprintf(a, "%0d", i);
> +        return(a);
>  }
> 
>  /* Insert the user defined arguments stored in user_arg into the $arg
> @@ -1380,24 +1454,33 @@ static char *
>  insert_args (line)
>       char *line;
>  {
> -  char *p, *save_line, *new_line;
> -  unsigned len, i;
> +  char *p, *save_line, *new_line, *afterarg;
> +  char envstr[256];
> +  unsigned len;
> +  int i;
> 
>    /* First we need to know how much memory to allocate for the new line.  */
>    save_line = line;
>    len = 0;
> -  while ((p = locate_arg (line)))
> +  while (locate_arg (line, &i/*argnum*/, &p/*startarg*/, &afterarg, envstr))
>      {
> -      len += p - line;
> -      i = p[4] - '0';
> -
> -      if (i >= user_args->count)
> -       {
> -         error ("Missing argument %d in user function.\n", i);
> -         return NULL;
> +      len += p - line; /* add portion before arg token */
> +      if (i == -1 && user_args)
> +        len += strlen(user_args->args);
> +      else if (i == -2 && user_args)
> +        len += strlen(itoa(user_args->count));
> +      else if (i == -3)
> +        len += strlen(envstr);
> +      else if (user_args && i < user_args->count)
> +        len += user_args->a[i].len;
> +/*
> +      else
> +        {
> +             error ("Missing argument %d in user function.\n", i);
> +             return NULL;
>         }
> -      len += user_args->a[i].len;
> -      line = p + 5;
> +*/
> +      line = afterarg;
>      }
> 
>    /* Don't forget the tail.  */
> @@ -1406,7 +1489,10 @@ insert_args (line)
>    /* Allocate space for the new line and fill it in.  */
>    new_line = (char *) xmalloc (len + 1);
>    if (new_line == NULL)
> -    return NULL;
> +    {
> +      error ("could not allocate memory for argument substitution.\n");
> +      return NULL;
> +    }
> 
>    /* Restore pointer to beginning of old line.  */
>    line = save_line;
> @@ -1414,21 +1500,36 @@ insert_args (line)
>    /* Save pointer to beginning of new line.  */
>    save_line = new_line;
> 
> -  while ((p = locate_arg (line)))
> +  while (locate_arg (line, &i/*argnum*/, &p/*startarg*/, &afterarg, envstr))
>      {
> -      int i, len;
> -
> -      memcpy (new_line, line, p - line);
> -      new_line += p - line;
> -      i = p[4] - '0';
> -
> -      len = user_args->a[i].len;
> -      if (len)
> -       {
> +      memcpy (new_line, line, p - line); /* copy line before arg token */
> +      new_line += p - line; /* point new_line at end */
> +      if (i == -1 && user_args)
> +        {
> +          len = strlen(user_args->args);
> +         memcpy (new_line, user_args->args, len);
> +        }
> +      else if (i == -2 && user_args)
> +        {
> +          len = strlen(itoa(user_args->count));
> +         memcpy (new_line, itoa(user_args->count), len);
> +        }
> +      else if (i == -3)
> +        {
> +          len = strlen(envstr);
> +         memcpy (new_line, envstr, len);
> +        }
> +      else if (user_args && i < user_args->count)
> +        {
> +          len = user_args->a[i].len;
>           memcpy (new_line, user_args->a[i].arg, len);
> -         new_line += len;
> -       }
> -      line = p + 5;
> +        }
> +      else
> +        {
> +         len = 0; /* arg not present - add nothing */
> +        }
> +      new_line += len;
> +      line = afterarg;
>      }
>    /* Don't forget the tail.  */
>    strcpy (new_line, line);
> @@ -1505,6 +1606,14 @@ execute_command (p, from_tty)
>        line = p;
> 
>        c = lookup_cmd (&p, cmdlist, "", 0, 1);
> +      if (c == (struct cmd_list_element *)-2) /* invoke shell? */
> +        {
> +          char *shellcmd;
> +          shellcmd = malloc(strlen(p)+7);
> +          sprintf(shellcmd, "shell %s", p);
> +          execute_command(shellcmd, from_tty);
> +          return;
> +        }
> 
>        /* If the target is running, we allow only a limited set of
>           commands. */
> @@ -1517,6 +1626,10 @@ execute_command (p, from_tty)
> 
>        /* Pass null arg rather than an empty one.  */
>        arg = *p ? p : 0;
> +      if (arg && c->function.cfunc != define_command
> +              && c->function.cfunc != shell_escape   )
> +         arg=insert_args(arg); /* replace environment variables in command with
> +                                  their values */
> 
>        /* Clear off trailing whitespace, except for set and complete command.  */
>        if (arg && c->type != set_cmd && c->function.cfunc != complete_command)
> 
> $ rcsdiff -up gdb/doc/gdb.info-9
> --- 1.1 2000/11/21 07:35:46
> +++ gdb/doc/gdb.info-9  2000/11/21 07:41:39
> @@ -250,12 +250,22 @@ User-defined commands
> 
>     A "user-defined command" is a sequence of GDB commands to which you
>  assign a new name as a command.  This is done with the `define'
> -command.  User commands may accept up to 10 arguments separated by
> +command.
> +
> +User commands may accept up to 10 arguments separated by
>  whitespace.  Arguments are accessed within the user command via
> -$ARG0...$ARG9.  A trivial example:
> +$ARG0...$ARG9 or $1...$9 and the 10th as ${10} or (${1}..${10}).
> +$# is the number of arguments given to the user-defined command.
> +A reference to an argument that is not given will be returned as an
> +empty string.
> +
> +You may also reference environment variables with ${ENV}, where ENV
> +is the name of the environment variable.
> +
> +A trivial example:
> 
>       define adder
> -       print $arg0 + $arg1 + $arg2
> +       print $1 + $2 + $3
> 
>  To execute the command use:
> 
> -Don

-- 
Fernando Nasser
Red Hat - Toronto                       E-Mail:  fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario   M4P 2C9




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]