This file is bind.def, from which is created bind.c.
It implements the builtin "bind" in Bash.

Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.

This file is part of GNU Bash, the Bourne Again SHell.

Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.

Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING.  If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

$PRODUCES bind.c

#include <config.h>

$BUILTIN bind
$DEPENDS_ON READLINE
$FUNCTION bind_builtin
$SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [keyseq:readline-function]
Bind a key sequence to a Readline function, or to a macro.  The
syntax is equivalent to that found in ~/.inputrc, but must be
passed as a single argument: bind '"\C-x\C-r": re-read-init-file'.
Arguments we accept:
  -m  keymap         Use `keymap' as the keymap for the duration of this
                     command.  Acceptable keymap names are emacs,
                     emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
                     vi-command, and vi-insert.
  -l                 List names of functions.
  -P                 List function names and bindings.
  -p                 List functions and bindings in a form that can be
                     reused as input.
  -r  keyseq         Remove the binding for KEYSEQ.
  -f  filename       Read key bindings from FILENAME.
  -q  function-name  Query about which keys invoke the named function.
  -u  function-name  Unbind all keys which are bound to the named function.
  -V                 List variable names and values
  -v                 List variable names and values in a form that can
                     be reused as input.
  -S                 List key sequences that invoke macros and their values
  -s                 List key sequences that invoke macros and their values in
                     a form that can be reused as input.
$END

#if defined (READLINE)

#if defined (HAVE_UNISTD_H)
#  ifdef _MINIX
#    include <sys/types.h>
#  endif
#  include <unistd.h>
#endif

#include <stdio.h>
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */

#include <readline/readline.h>
#include <readline/history.h>

#include "../shell.h"
#include "../bashline.h"
#include "bashgetopt.h"
#include "common.h"

static int query_bindings ();
static int unbind_command ();

extern int no_line_editing;

#define BIND_RETURN(x)  do { return_code = x; goto bind_exit; } while (0)

#define LFLAG	0x0001
#define PFLAG	0x0002
#define FFLAG	0x0004
#define VFLAG	0x0008
#define QFLAG	0x0010
#define MFLAG	0x0020
#define RFLAG	0x0040
#define PPFLAG	0x0080
#define VVFLAG	0x0100
#define SFLAG   0x0200
#define SSFLAG  0x0400
#define UFLAG	0x0800

int
bind_builtin (list)
     WORD_LIST *list;
{
  int return_code;
  FILE *old_rl_outstream;
  Keymap kmap, saved_keymap;
  int flags, opt;
  char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq;

  if (no_line_editing)
    return (EXECUTION_FAILURE);

  kmap = saved_keymap = (Keymap) NULL;
  flags = 0;
  initfile = map_name = fun_name = unbind_name = remove_seq = (char *)NULL;
  return_code = EXECUTION_SUCCESS;

  if (!bash_readline_initialized)
    initialize_readline ();

  /* Cannot use unwind_protect_pointer () on "FILE *", it is only
     guaranteed to work for strings. */
  /* XXX -- see if we can use unwind_protect here */
  old_rl_outstream = rl_outstream;
  rl_outstream = stdout;

  reset_internal_getopt ();  
  while ((opt = internal_getopt (list, "lvpVPsSf:q:u:m:r:")) != EOF)
    {
      switch (opt)
	{
	case 'l':
	  flags |= LFLAG;
	  break;
	case 'v':
	  flags |= VFLAG;
	  break;
	case 'p':
	  flags |= PFLAG;
	  break;
	case 'f':
	  flags |= FFLAG;
	  initfile = list_optarg;
	  break;
	case 'm':
	  flags |= MFLAG;
	  map_name = list_optarg;
	  break;
	case 'q':
	  flags |= QFLAG;
	  fun_name = list_optarg;
	  break;
	case 'u':
	  flags |= UFLAG;
	  unbind_name = list_optarg;
	  break;
	case 'r':
	  flags |= RFLAG;
	  remove_seq = list_optarg;
	  break;
	case 'V':
	  flags |= VVFLAG;
	  break;
	case 'P':
	  flags |= PPFLAG;
	  break;
	case 's':
	  flags |= SFLAG;
	  break;
	case 'S':
	  flags |= SSFLAG;
	  break;
	default:
	  builtin_usage ();
	  BIND_RETURN (EX_USAGE);
	}
    }

  list = loptend;

  /* First, see if we need to install a special keymap for this
     command.  Then start on the arguments. */

  if ((flags & MFLAG) && map_name)
    {
      kmap = rl_get_keymap_by_name (map_name);
      if (!kmap)
        {
	  builtin_error ("`%s': invalid keymap name", map_name);
	  BIND_RETURN (EXECUTION_FAILURE);
        }
    }

  if (kmap)
    {
      saved_keymap = rl_get_keymap ();
      rl_set_keymap (kmap);
    }

  /* XXX - we need to add exclusive use tests here.  It doesn't make sense
     to use some of these options together. */
  /* Now hack the option arguments */
  if (flags & LFLAG)
    rl_list_funmap_names ();

  if (flags & PFLAG)
    rl_function_dumper (1);

  if (flags & PPFLAG)
    rl_function_dumper (0);

  if (flags & SFLAG)
    rl_macro_dumper (1);

  if (flags & SSFLAG)
    rl_macro_dumper (0);

  if (flags & VFLAG)
    rl_variable_dumper (1);

  if (flags & VVFLAG)
    rl_variable_dumper (0);

  if ((flags & FFLAG) && initfile)
    {
      if (rl_read_init_file (initfile) != 0)
	{
	  builtin_error ("cannot read %s: %s", initfile, strerror (errno));
	  BIND_RETURN (EXECUTION_FAILURE);
	}
    }

  if ((flags & QFLAG) && fun_name)
    return_code = query_bindings (fun_name);

  if ((flags & UFLAG) && unbind_name)
    return_code = unbind_command (unbind_name);

  if ((flags & RFLAG) && remove_seq)
    {
      if (rl_set_key (remove_seq, (Function *)NULL, rl_get_keymap ()) != 0)
	{
	  builtin_error ("cannot unbind %s", remove_seq);
	  BIND_RETURN (EXECUTION_FAILURE);
	}
    }

  /* Process the rest of the arguments as binding specifications. */
  while (list)
    {
      rl_parse_and_bind (list->word->word);
      list = list->next;
    }

 bind_exit:
  if (saved_keymap)
    rl_set_keymap (saved_keymap);

  rl_outstream = old_rl_outstream;
  return (return_code);
}

static int
query_bindings (name)
     char *name;
{
  Function *function;
  char **keyseqs;
  int j;

  function = rl_named_function (name);
  if (function == 0)
    {
      builtin_error ("unknown function name `%s'", name);
      return EXECUTION_FAILURE;
    }

  keyseqs = rl_invoking_keyseqs (function);

  if (!keyseqs)
    {
      printf ("%s is not bound to any keys.\n", name);
      return EXECUTION_FAILURE;
    }

  printf ("%s can be invoked via ", name);
  for (j = 0; j < 5 && keyseqs[j]; j++)
    printf ("\"%s\"%s", keyseqs[j], keyseqs[j + 1] ? ", " : ".\n");
  if (keyseqs[j])
    printf ("...\n");
  free_array (keyseqs);
  return EXECUTION_SUCCESS;
}

static int
unbind_command (name)
     char *name;
{
  Function *function;

  function = rl_named_function (name);
  if (function == 0)
    {
      builtin_error ("unknown function name `%s'", name);
      return EXECUTION_FAILURE;
    }

  rl_unbind_function_in_map (function, rl_get_keymap ());
  return EXECUTION_SUCCESS;
}
#endif /* READLINE */
