home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / readline / bind.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  35KB  |  1,456 lines

  1. /* bind.c -- key binding and startup file support for the readline library. */
  2.  
  3. /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
  4.  
  5.    This file is part of the GNU Readline Library, a library for
  6.    reading lines of text with interactive input and history editing.
  7.  
  8.    The GNU Readline Library is free software; you can redistribute it
  9.    and/or modify it under the terms of the GNU General Public License
  10.    as published by the Free Software Foundation; either version 1, or
  11.    (at your option) any later version.
  12.  
  13.    The GNU Readline Library is distributed in the hope that it will be
  14.    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  15.    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.  
  18.    The GNU General Public License is often shipped with GNU software, and
  19.    is generally kept in a file called COPYING or LICENSE.  If you do not
  20.    have a copy of the license, write to the Free Software Foundation,
  21.    675 Mass Ave, Cambridge, MA 02139, USA. */
  22.  
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #include <fcntl.h>
  26. #if !defined (NO_SYS_FILE)
  27. #  include <sys/file.h>
  28. #endif /* !NO_SYS_FILE */
  29. #include <signal.h>
  30.  
  31. #if defined (HAVE_UNISTD_H)
  32. #  include <unistd.h>
  33. #endif /* HAVE_UNISTD_H */
  34.  
  35. #if defined (HAVE_STDLIB_H)
  36. #  include <stdlib.h>
  37. #else
  38. #  include "ansi_stdlib.h"
  39. #endif /* HAVE_STDLIB_H */
  40.  
  41. #include <errno.h>
  42. /* Not all systems declare ERRNO in errno.h... and some systems #define it! */
  43. #if !defined (errno)
  44. extern int errno;
  45. #endif /* !errno */
  46.  
  47. #include "posixstat.h"
  48.  
  49. /* System-specific feature definitions and include files. */
  50. #include "rldefs.h"
  51.  
  52. /* Some standard library routines. */
  53. #include "readline.h"
  54. #include "history.h"
  55.  
  56. #if !defined (strchr) && !defined (__STDC__)
  57. extern char *strchr (), *strrchr ();
  58. #endif /* !strchr && !__STDC__ */
  59.  
  60. extern char *tilde_expand ();
  61.  
  62. extern int _rl_horizontal_scroll_mode;
  63. extern int _rl_mark_modified_lines;
  64. extern int _rl_prefer_visible_bell;
  65. extern int _rl_meta_flag;
  66. extern int rl_blink_matching_paren;
  67. extern int _rl_convert_meta_chars_to_ascii;
  68. #if defined (VISIBLE_STATS)
  69. extern int rl_visible_stats;
  70. #endif /* VISIBLE_STATS */
  71. extern int rl_complete_with_tilde_expansion;
  72. extern int rl_completion_query_items;
  73.  
  74. extern int rl_explicit_arg;
  75. extern int rl_editing_mode;
  76. extern unsigned short _rl_parsing_conditionalized_out;
  77. extern Keymap _rl_keymap;
  78.  
  79. extern char *possible_control_prefixes[], *possible_meta_prefixes[];
  80.  
  81. extern char **rl_funmap_names ();
  82.  
  83. static int glean_key_from_name ();
  84. #ifndef HAVE_STRICMP
  85. static int stricmp ();
  86. #endif
  87. #ifndef HAVE_STRNICMP
  88. static int strnicmp ();
  89. #endif
  90.  
  91. #if defined (STATIC_MALLOC)
  92. static char *xmalloc (), *xrealloc ();
  93. #else
  94. extern char *xmalloc (), *xrealloc ();
  95. #endif /* STATIC_MALLOC */
  96.  
  97. /* Defined in this file */
  98. extern int
  99.   rl_bind_key (), rl_generic_bind (), rl_translate_keyseq (),
  100.   rl_read_init_file (), rl_parse_and_bind (), rl_variable_bind ();
  101.  
  102. /* Defined in funmap.c */
  103. extern int rl_add_funmap_entry ();
  104. extern void rl_initialize_funmap ();
  105.  
  106. /* Defined in display.c */
  107. extern int rl_on_new_line ();
  108.  
  109. /* **************************************************************** */
  110. /*                                    */
  111. /*            Binding keys                    */
  112. /*                                    */
  113. /* **************************************************************** */
  114.  
  115. /* rl_add_defun (char *name, Function *function, int key)
  116.    Add NAME to the list of named functions.  Make FUNCTION be the function
  117.    that gets called.  If KEY is not -1, then bind it. */
  118. int
  119. rl_add_defun (name, function, key)
  120.      char *name;
  121.      Function *function;
  122.      int key;
  123. {
  124.   if (key != -1)
  125.     rl_bind_key (key, function);
  126.   rl_add_funmap_entry (name, function);
  127.   return 0;
  128. }
  129.  
  130. /* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
  131. int
  132. rl_bind_key (key, function)
  133.      int key;
  134.      Function *function;
  135. {
  136.   if (key < 0)
  137.     return (key);
  138.  
  139.   if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
  140.     {
  141.       if (_rl_keymap[ESC].type == ISKMAP)
  142.     {
  143. #if defined (CRAY)
  144.       Keymap escmap = (Keymap)((int)_rl_keymap[ESC].function);
  145. #else
  146.       Keymap escmap = (Keymap)_rl_keymap[ESC].function;
  147. #endif
  148.  
  149.       key = UNMETA (key);
  150.       escmap[key].type = ISFUNC;
  151.       escmap[key].function = function;
  152.       return (0);
  153.     }
  154.       return (key);
  155.     }
  156.  
  157.   _rl_keymap[key].type = ISFUNC;
  158.   _rl_keymap[key].function = function;
  159.   return (0);
  160. }
  161.  
  162. /* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
  163.    KEY. */
  164. int
  165. rl_bind_key_in_map (key, function, map)
  166.      int key;
  167.      Function *function;
  168.      Keymap map;
  169. {
  170.   int result;
  171.   Keymap oldmap = _rl_keymap;
  172.  
  173.   _rl_keymap = map;
  174.   result = rl_bind_key (key, function);
  175.   _rl_keymap = oldmap;
  176.   return (result);
  177. }
  178.  
  179. /* Make KEY do nothing in the currently selected keymap.
  180.    Returns non-zero in case of error. */
  181. int
  182. rl_unbind_key (key)
  183.      int key;
  184. {
  185.   return (rl_bind_key (key, (Function *)NULL));
  186. }
  187.  
  188. /* Make KEY do nothing in MAP.
  189.    Returns non-zero in case of error. */
  190. int
  191. rl_unbind_key_in_map (key, map)
  192.      int key;
  193.      Keymap map;
  194. {
  195.   return (rl_bind_key_in_map (key, (Function *)NULL, map));
  196. }
  197.  
  198. /* Bind the key sequence represented by the string KEYSEQ to
  199.    FUNCTION.  This makes new keymaps as necessary.  The initial
  200.    place to do bindings is in MAP. */
  201. int
  202. rl_set_key (keyseq, function, map)
  203.      char *keyseq;
  204.      Function *function;
  205.      Keymap map;
  206. {
  207.   rl_generic_bind (ISFUNC, keyseq, function, map);
  208.   return 0;
  209. }
  210.  
  211. /* Bind the key sequence represented by the string KEYSEQ to
  212.    the string of characters MACRO.  This makes new keymaps as
  213.    necessary.  The initial place to do bindings is in MAP. */
  214. int
  215. rl_macro_bind (keyseq, macro, map)
  216.      char *keyseq, *macro;
  217.      Keymap map;
  218. {
  219.   char *macro_keys;
  220.   int macro_keys_len;
  221.  
  222.   macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
  223.  
  224.   if (rl_translate_keyseq (macro, macro_keys, ¯o_keys_len))
  225.     {
  226.       free (macro_keys);
  227.       return -1;
  228.     }
  229.   rl_generic_bind (ISMACR, keyseq, macro_keys, map);
  230.   return 0;
  231. }
  232.  
  233. /* Bind the key sequence represented by the string KEYSEQ to
  234.    the arbitrary pointer DATA.  TYPE says what kind of data is
  235.    pointed to by DATA, right now this can be a function (ISFUNC),
  236.    a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
  237.    as necessary.  The initial place to do bindings is in MAP. */
  238. int
  239. rl_generic_bind (type, keyseq, data, map)
  240.      int type;
  241.      char *keyseq, *data;
  242.      Keymap map;
  243. {
  244.   char *keys;
  245.   int keys_len;
  246.   register int i;
  247.  
  248.   /* If no keys to bind to, exit right away. */
  249.   if (!keyseq || !*keyseq)
  250.     {
  251.       if (type == ISMACR)
  252.     free (data);
  253.       return -1;
  254.     }
  255.  
  256.   keys = xmalloc (1 + (2 * strlen (keyseq)));
  257.  
  258.   /* Translate the ASCII representation of KEYSEQ into an array of
  259.      characters.  Stuff the characters into KEYS, and the length of
  260.      KEYS into KEYS_LEN. */
  261.   if (rl_translate_keyseq (keyseq, keys, &keys_len))
  262.     {
  263.       free (keys);
  264.       return -1;
  265.     }
  266.  
  267.   /* Bind keys, making new keymaps as necessary. */
  268.   for (i = 0; i < keys_len; i++)
  269.     {
  270.       int ic = (int) ((unsigned char)keys[i]);
  271.  
  272.       if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic))
  273.     {
  274.       ic = UNMETA (ic);
  275.       if (map[ESC].type == ISKMAP)
  276.         map = (Keymap) map[ESC].function;
  277.     }
  278.  
  279.       if ((i + 1) < keys_len)
  280.     {
  281.       if (map[ic].type != ISKMAP)
  282.         {
  283.           if (map[ic].type == ISMACR)
  284.         free ((char *)map[ic].function);
  285.  
  286.           map[ic].type = ISKMAP;
  287.           map[ic].function = (Function *)rl_make_bare_keymap ();
  288.         }
  289.       map = (Keymap)map[ic].function;
  290.     }
  291.       else
  292.     {
  293.       if (map[ic].type == ISMACR)
  294.         free ((char *)map[ic].function);
  295.  
  296.       map[ic].function = (Function *)data;
  297.       map[ic].type = type;
  298.     }
  299.     }
  300.   free (keys);
  301.   return 0;
  302. }
  303.  
  304. /* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
  305.    an array of characters.  LEN gets the final length of ARRAY.  Return
  306.    non-zero if there was an error parsing SEQ. */
  307. int
  308. rl_translate_keyseq (seq, array, len)
  309.      char *seq, *array;
  310.      int *len;
  311. {
  312.   register int i, c, l = 0;
  313.  
  314.   for (i = 0; (c = seq[i]) != '\0'; i++)
  315.     {
  316.       if (c == '\\')
  317.     {
  318.       c = seq[++i];
  319.  
  320.       if (!c)
  321.         break;
  322.  
  323.       if (((c == 'C' || c == 'M') &&  seq[i + 1] == '-') ||
  324.           (c == 'e'))
  325.         {
  326.           /* Handle special case of backwards define. */
  327.           if (strncmp (&seq[i], "C-\\M-", 5) == 0)
  328.         {
  329.           array[l++] = ESC;
  330.           i += 5;
  331.           array[l++] = CTRL (to_upper (seq[i]));
  332.           if (!seq[i])
  333.             i--;
  334.           continue;
  335.         }
  336.  
  337.           switch (c)
  338.         {
  339.         case 'M':
  340.           i++;
  341.           array[l++] = ESC;
  342.           break;
  343.  
  344.         case 'C':
  345.           i += 2;
  346.           /* Special hack for C-?... */
  347.           if (seq[i] == '?')
  348.             array[l++] = RUBOUT;
  349.           else
  350.             array[l++] = CTRL (to_upper (seq[i]));
  351.           break;
  352.  
  353.         case 'e':
  354.           array[l++] = ESC;
  355.         }
  356.  
  357.           continue;
  358.         }
  359.     }
  360.       array[l++] = c;
  361.     }
  362.  
  363.   *len = l;
  364.   array[l] = '\0';
  365.   return (0);
  366. }
  367.  
  368. /* Return a pointer to the function that STRING represents.
  369.    If STRING doesn't have a matching function, then a NULL pointer
  370.    is returned. */
  371. Function *
  372. rl_named_function (string)
  373.      char *string;
  374. {
  375.   register int i;
  376.  
  377.   rl_initialize_funmap ();
  378.  
  379.   for (i = 0; funmap[i]; i++)
  380.     if (stricmp (funmap[i]->name, string) == 0)
  381.       return (funmap[i]->function);
  382.   return ((Function *)NULL);
  383. }
  384.  
  385. /* Return the function (or macro) definition which would be invoked via
  386.    KEYSEQ if executed in MAP.  If MAP is NULL, then the current keymap is
  387.    used.  TYPE, if non-NULL, is a pointer to an int which will receive the
  388.    type of the object pointed to.  One of ISFUNC (function), ISKMAP (keymap),
  389.    or ISMACR (macro). */
  390. Function *
  391. rl_function_of_keyseq (keyseq, map, type)
  392.      char *keyseq;
  393.      Keymap map;
  394.      int *type;
  395. {
  396.   register int i;
  397.  
  398.   if (!map)
  399.     map = _rl_keymap;
  400.  
  401.   for (i = 0; keyseq && keyseq[i]; i++)
  402.     {
  403.       int ic = keyseq[i];
  404.  
  405.       if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
  406.     {
  407.       if (map[ESC].type != ISKMAP)
  408.         {
  409.           if (type)
  410.         *type = map[ESC].type;
  411.  
  412.           return (map[ESC].function);
  413.         }
  414.       else
  415.         {
  416.           map = (Keymap)map[ESC].function;
  417.           ic = UNMETA (ic);
  418.         }
  419.     }
  420.  
  421.       if (map[ic].type == ISKMAP)
  422.     {
  423.       /* If this is the last key in the key sequence, return the
  424.          map. */
  425.       if (!keyseq[i + 1])
  426.         {
  427.           if (type)
  428.         *type = ISKMAP;
  429.  
  430.           return (map[ic].function);
  431.         }
  432.       else
  433.         map = (Keymap)map[ic].function;
  434.     }
  435.       else
  436.     {
  437.       if (type)
  438.         *type = map[ic].type;
  439.  
  440.       return (map[ic].function);
  441.     }
  442.     }
  443.  
  444.   return NULL;
  445. }
  446.  
  447. /* The last key bindings file read. */
  448. static char *last_readline_init_file = (char *)NULL;
  449.  
  450. /* Re-read the current keybindings file. */
  451. int
  452. rl_re_read_init_file (count, ignore)
  453.      int count, ignore;
  454. {
  455.   return (rl_read_init_file ((char *)NULL));
  456. }
  457.  
  458. /* The final, last-ditch effort file name for an init file. */
  459. #define DEFAULT_INPUTRC "~/.inputrc"
  460.  
  461. /* Do key bindings from a file.  If FILENAME is NULL it defaults
  462.    to `~/.inputrc'.  If the file existed and could be opened and
  463.    read, 0 is returned, otherwise errno is returned. */
  464. int
  465. rl_read_init_file (filename)
  466.      char *filename;
  467. {
  468.   register int i;
  469.   char *buffer, *openname, *line, *end;
  470.   struct stat finfo;
  471.   int file;
  472.  
  473.   /* Default the filename. */
  474.   if (!filename)
  475.     {
  476.       if (last_readline_init_file)
  477.     filename = last_readline_init_file;
  478.       else
  479.     filename = DEFAULT_INPUTRC;
  480.     }
  481.  
  482.   openname = tilde_expand (filename);
  483.  
  484.   if ((stat (openname, &finfo) < 0) ||
  485.       (file = open (openname, O_RDONLY, 0666)) < 0)
  486.     {
  487.       free (openname);
  488.       return (errno);
  489.     }
  490.   else
  491.     free (openname);
  492.  
  493.   if (last_readline_init_file)
  494.     free (last_readline_init_file);
  495.  
  496.   last_readline_init_file = savestring (filename);
  497.  
  498.   /* Read the file into BUFFER. */
  499.   buffer = (char *)xmalloc ((int)finfo.st_size + 1);
  500.   i = read (file, buffer, finfo.st_size);
  501.   close (file);
  502.  
  503.   if (i != finfo.st_size)
  504.     return (errno);
  505.  
  506.   /* Loop over the lines in the file.  Lines that start with `#' are
  507.      comments; all other lines are commands for readline initialization. */
  508.   line = buffer;
  509.   end = buffer + finfo.st_size;
  510.   while (line < end)
  511.     {
  512.       /* Find the end of this line. */
  513.       for (i = 0; line + i != end && line[i] != '\n'; i++);
  514.  
  515.       /* Mark end of line. */
  516.       line[i] = '\0';
  517.  
  518.       /* If the line is not a comment, then parse it. */
  519.       if (*line && *line != '#')
  520.     rl_parse_and_bind (line);
  521.  
  522.       /* Move to the next line. */
  523.       line += i + 1;
  524.     }
  525.   free (buffer);
  526.   return (0);
  527. }
  528.  
  529. /* **************************************************************** */
  530. /*                                    */
  531. /*            Parser Directives                   */
  532. /*                                    */
  533. /* **************************************************************** */
  534.  
  535. /* Conditionals. */
  536.  
  537. /* Calling programs set this to have their argv[0]. */
  538. char *rl_readline_name = "other";
  539.  
  540. /* Stack of previous values of parsing_conditionalized_out. */
  541. static unsigned char *if_stack = (unsigned char *)NULL;
  542. static int if_stack_depth = 0;
  543. static int if_stack_size = 0;
  544.  
  545. /* Push _rl_parsing_conditionalized_out, and set parser state based
  546.    on ARGS. */
  547. static int
  548. parser_if (args)
  549.      char *args;
  550. {
  551.   register int i;
  552.  
  553.   /* Push parser state. */
  554.   if (if_stack_depth + 1 >= if_stack_size)
  555.     {
  556.       if (!if_stack)
  557.     if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
  558.       else
  559.     if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
  560.     }
  561.   if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
  562.  
  563.   /* If parsing is turned off, then nothing can turn it back on except
  564.      for finding the matching endif.  In that case, return right now. */
  565.   if (_rl_parsing_conditionalized_out)
  566.     return 0;
  567.  
  568.   /* Isolate first argument. */
  569.   for (i = 0; args[i] && !whitespace (args[i]); i++);
  570.  
  571.   if (args[i])
  572.     args[i++] = '\0';
  573.  
  574.   /* Handle "if term=foo" and "if mode=emacs" constructs.  If this
  575.      isn't term=foo, or mode=emacs, then check to see if the first
  576.      word in ARGS is the same as the value stored in rl_readline_name. */
  577.   if (rl_terminal_name && strnicmp (args, "term=", 5) == 0)
  578.     {
  579.       char *tem, *tname;
  580.  
  581.       /* Terminals like "aaa-60" are equivalent to "aaa". */
  582.       tname = savestring (rl_terminal_name);
  583.       tem = strrchr (tname, '-');
  584.       if (tem)
  585.     *tem = '\0';
  586.  
  587.       /* Test the `long' and `short' forms of the terminal name so that
  588.      if someone has a `sun-cmd' and does not want to have bindings
  589.      that will be executed if the terminal is a `sun', they can put
  590.      `$if term=sun-cmd' into their .inputrc. */
  591.       if ((stricmp (args + 5, tname) == 0) ||
  592.       (stricmp (args + 5, rl_terminal_name) == 0))
  593.     _rl_parsing_conditionalized_out = 0;
  594.       else
  595.     _rl_parsing_conditionalized_out = 1;
  596.  
  597.       free (tname);
  598.     }
  599. #if defined (VI_MODE)
  600.   else if (strnicmp (args, "mode=", 5) == 0)
  601.     {
  602.       int mode;
  603.  
  604.       if (stricmp (args + 5, "emacs") == 0)
  605.     mode = emacs_mode;
  606.       else if (stricmp (args + 5, "vi") == 0)
  607.     mode = vi_mode;
  608.       else
  609.     mode = no_mode;
  610.  
  611.       if (mode == rl_editing_mode)
  612.     _rl_parsing_conditionalized_out = 0;
  613.       else
  614.     _rl_parsing_conditionalized_out = 1;
  615.     }
  616. #endif /* VI_MODE */
  617.   /* Check to see if the first word in ARGS is the same as the
  618.      value stored in rl_readline_name. */
  619.   else if (stricmp (args, rl_readline_name) == 0)
  620.     _rl_parsing_conditionalized_out = 0;
  621.   else
  622.     _rl_parsing_conditionalized_out = 1;
  623.   return 0;
  624. }
  625.  
  626. /* Invert the current parser state if there is anything on the stack. */
  627. static int
  628. parser_else (args)
  629.      char *args;
  630. {
  631.   register int i;
  632.  
  633.   if (!if_stack_depth)
  634.     {
  635.       /* Error message? */
  636.       return 0;
  637.     }
  638.  
  639.   /* Check the previous (n - 1) levels of the stack to make sure that
  640.      we haven't previously turned off parsing. */
  641.   for (i = 0; i < if_stack_depth - 1; i++)
  642.     if (if_stack[i] == 1)
  643.       return 0;
  644.  
  645.   /* Invert the state of parsing if at top level. */
  646.   _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
  647.   return 0;
  648. }
  649.  
  650. /* Terminate a conditional, popping the value of
  651.    _rl_parsing_conditionalized_out from the stack. */
  652. static int
  653. parser_endif (args)
  654.      char *args;
  655. {
  656.   if (if_stack_depth)
  657.     _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
  658.   else
  659.     {
  660.       /* *** What, no error message? *** */
  661.     }
  662.   return 0;
  663. }
  664.  
  665. /* Associate textual names with actual functions. */
  666. static struct {
  667.   char *name;
  668.   Function *function;
  669. } parser_directives [] = {
  670.   { "if", parser_if },
  671.   { "endif", parser_endif },
  672.   { "else", parser_else },
  673.   { (char *)0x0, (Function *)0x0 }
  674. };
  675.  
  676. /* Handle a parser directive.  STATEMENT is the line of the directive
  677.    without any leading `$'. */
  678. static int
  679. handle_parser_directive (statement)
  680.      char *statement;
  681. {
  682.   register int i;
  683.   char *directive, *args;
  684.  
  685.   /* Isolate the actual directive. */
  686.  
  687.   /* Skip whitespace. */
  688.   for (i = 0; whitespace (statement[i]); i++);
  689.  
  690.   directive = &statement[i];
  691.  
  692.   for (; statement[i] && !whitespace (statement[i]); i++);
  693.  
  694.   if (statement[i])
  695.     statement[i++] = '\0';
  696.  
  697.   for (; statement[i] && whitespace (statement[i]); i++);
  698.  
  699.   args = &statement[i];
  700.  
  701.   /* Lookup the command, and act on it. */
  702.   for (i = 0; parser_directives[i].name; i++)
  703.     if (stricmp (directive, parser_directives[i].name) == 0)
  704.       {
  705.     (*parser_directives[i].function) (args);
  706.     return (0);
  707.       }
  708.  
  709.   /* *** Should an error message be output? */
  710.   return (1);
  711. }
  712.  
  713. /* Ugly but working hack for binding prefix meta. */
  714. #define PREFIX_META_HACK
  715.  
  716. static int substring_member_of_array ();
  717.  
  718. /* Read the binding command from STRING and perform it.
  719.    A key binding command looks like: Keyname: function-name\0,
  720.    a variable binding command looks like: set variable value.
  721.    A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
  722. int
  723. rl_parse_and_bind (string)
  724.      char *string;
  725. {
  726.   char *funname, *kname;
  727.   register int c, i;
  728.   int key, equivalency;
  729.  
  730.   while (string && whitespace (*string))
  731.     string++;
  732.  
  733.   if (!string || !*string || *string == '#')
  734.     return 0;
  735.  
  736.   /* If this is a parser directive, act on it. */
  737.   if (*string == '$')
  738.     {
  739.       handle_parser_directive (&string[1]);
  740.       return 0;
  741.     }
  742.  
  743.   /* If we aren't supposed to be parsing right now, then we're done. */
  744.   if (_rl_parsing_conditionalized_out)
  745.     return 0;
  746.  
  747.   i = 0;
  748.   /* If this keyname is a complex key expression surrounded by quotes,
  749.      advance to after the matching close quote.  This code allows the
  750.      backslash to quote characters in the key expression. */
  751.   if (*string == '"')
  752.     {
  753.       int passc = 0;
  754.  
  755.       for (i = 1; (c = string[i]) != '\0'; i++)
  756.     {
  757.       if (passc)
  758.         {
  759.           passc = 0;
  760.           continue;
  761.         }
  762.  
  763.       if (c == '\\')
  764.         {
  765.           passc++;
  766.           continue;
  767.         }
  768.  
  769.       if (c == '"')
  770.         break;
  771.     }
  772.     }
  773.  
  774.   /* Advance to the colon (:) or whitespace which separates the two objects. */
  775.   for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
  776.  
  777.   equivalency = (c == ':' && string[i + 1] == '=');
  778.  
  779.   /* Mark the end of the command (or keyname). */
  780.   if (string[i])
  781.     string[i++] = '\0';
  782.  
  783.   /* If doing assignment, skip the '=' sign as well. */
  784.   if (equivalency)
  785.     string[i++] = '\0';
  786.  
  787.   /* If this is a command to set a variable, then do that. */
  788.   if (stricmp (string, "set") == 0)
  789.     {
  790.       char *var = string + i;
  791.       char *value;
  792.  
  793.       /* Make VAR point to start of variable name. */
  794.       while (*var && whitespace (*var)) var++;
  795.  
  796.       /* Make value point to start of value string. */
  797.       value = var;
  798.       while (*value && !whitespace (*value)) value++;
  799.       if (*value)
  800.     *value++ = '\0';
  801.       while (*value && whitespace (*value)) value++;
  802.  
  803.       rl_variable_bind (var, value);
  804.       return 0;
  805.     }
  806.  
  807.   /* Skip any whitespace between keyname and funname. */
  808.   for (; string[i] && whitespace (string[i]); i++);
  809.   funname = &string[i];
  810.  
  811.   /* Now isolate funname.
  812.      For straight function names just look for whitespace, since
  813.      that will signify the end of the string.  But this could be a
  814.      macro definition.  In that case, the string is quoted, so skip
  815.      to the matching delimiter.  We allow the backslash to quote the
  816.      delimiter characters in the macro body. */
  817.   /* This code exists to allow whitespace in macro expansions, which
  818.      would otherwise be gobbled up by the next `for' loop.*/
  819.   /* XXX - it may be desirable to allow backslash quoting only if " is
  820.      the quoted string delimiter, like the shell. */
  821.   if (*funname == '\'' || *funname == '"')
  822.     {
  823.       int delimiter = string[i++];
  824.       int passc = 0;
  825.  
  826.       for (; (c = string[i]) != '\0'; i++)
  827.     {
  828.       if (passc)
  829.         {
  830.           passc = 0;
  831.           continue;
  832.         }
  833.  
  834.       if (c == '\\')
  835.         {
  836.           passc = 1;
  837.           continue;
  838.         }
  839.  
  840.       if (c == delimiter)
  841.         break;
  842.     }
  843.       if (c)
  844.     i++;
  845.     }
  846.  
  847.   /* Advance to the end of the string.  */
  848.   for (; string[i] && !whitespace (string[i]); i++);
  849.  
  850.   /* No extra whitespace at the end of the string. */
  851.   string[i] = '\0';
  852.  
  853.   /* Handle equivalency bindings here.  Make the left-hand side be exactly
  854.      whatever the right-hand evaluates to, including keymaps. */
  855.   if (equivalency)
  856.     {
  857.       return 0;
  858.     }
  859.  
  860.   /* If this is a new-style key-binding, then do the binding with
  861.      rl_set_key ().  Otherwise, let the older code deal with it. */
  862.   if (*string == '"')
  863.     {
  864.       char *seq = xmalloc (1 + strlen (string));
  865.       register int j, k = 0;
  866.       int passc = 0;
  867.  
  868.       for (j = 1; string[j]; j++)
  869.     {
  870.       /* Allow backslash to quote characters, but leave them in place.
  871.          This allows a string to end with a backslash quoting another
  872.          backslash, or with a backslash quoting a double quote.  The
  873.          backslashes are left in place for rl_translate_keyseq (). */
  874.       if (passc || (string[j] == '\\'))
  875.         {
  876.           seq[k++] = string[j];
  877.           passc = !passc;
  878.           continue;
  879.         }
  880.  
  881.       if (string[j] == '"')
  882.         break;
  883.  
  884.       seq[k++] = string[j];
  885.     }
  886.       seq[k] = '\0';
  887.  
  888.       /* Binding macro? */
  889.       if (*funname == '\'' || *funname == '"')
  890.     {
  891.       j = strlen (funname);
  892.  
  893.       /* Remove the delimiting quotes from each end of FUNNAME. */
  894.       if (j && funname[j - 1] == *funname)
  895.         funname[j - 1] = '\0';
  896.  
  897.       rl_macro_bind (seq, &funname[1], _rl_keymap);
  898.     }
  899.       else
  900.     rl_set_key (seq, rl_named_function (funname), _rl_keymap);
  901.  
  902.       free (seq);
  903.       return 0;
  904.     }
  905.  
  906.   /* Get the actual character we want to deal with. */
  907.   kname = strrchr (string, '-');
  908.   if (!kname)
  909.     kname = string;
  910.   else
  911.     kname++;
  912.  
  913.   key = glean_key_from_name (kname);
  914.  
  915.   /* Add in control and meta bits. */
  916.   if (substring_member_of_array (string, possible_control_prefixes))
  917.     key = CTRL (to_upper (key));
  918.  
  919.   if (substring_member_of_array (string, possible_meta_prefixes))
  920.     key = META (key);
  921.  
  922.   /* Temporary.  Handle old-style keyname with macro-binding. */
  923.   if (*funname == '\'' || *funname == '"')
  924.     {
  925.       char seq[2];
  926.       int fl = strlen (funname);
  927.  
  928.       seq[0] = key; seq[1] = '\0';
  929.       if (fl && funname[fl - 1] == *funname)
  930.     funname[fl - 1] = '\0';
  931.  
  932.       rl_macro_bind (seq, &funname[1], _rl_keymap);
  933.     }
  934. #if defined (PREFIX_META_HACK)
  935.   /* Ugly, but working hack to keep prefix-meta around. */
  936.   else if (stricmp (funname, "prefix-meta") == 0)
  937.     {
  938.       char seq[2];
  939.  
  940.       seq[0] = key;
  941.       seq[1] = '\0';
  942.       rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
  943.     }
  944. #endif /* PREFIX_META_HACK */
  945.   else
  946.     rl_bind_key (key, rl_named_function (funname));
  947.   return 0;
  948. }
  949.  
  950. /* Simple structure for boolean readline variables (i.e., those that can
  951.    have one of two values; either "On" or 1 for truth, or "Off" or 0 for
  952.    false. */
  953.  
  954. static struct {
  955.   char *name;
  956.   int *value;
  957. } boolean_varlist [] = {
  958.   { "horizontal-scroll-mode",    &_rl_horizontal_scroll_mode },
  959.   { "mark-modified-lines",    &_rl_mark_modified_lines },
  960.   { "prefer-visible-bell",    &_rl_prefer_visible_bell },
  961.   { "meta-flag",        &_rl_meta_flag },
  962.   { "blink-matching-paren",    &rl_blink_matching_paren },
  963.   { "convert-meta",        &_rl_convert_meta_chars_to_ascii },
  964. #if defined (VISIBLE_STATS)
  965.   { "visible-stats",        &rl_visible_stats },
  966. #endif /* VISIBLE_STATS */
  967.   { "expand-tilde",        &rl_complete_with_tilde_expansion },
  968.   { (char *)NULL, (int *)NULL }
  969. };
  970.  
  971. int
  972. rl_variable_bind (name, value)
  973.      char *name, *value;
  974. {
  975.   register int i;
  976.  
  977.   /* Check for simple variables first. */
  978.   for (i = 0; boolean_varlist[i].name; i++)
  979.     {
  980.       if (stricmp (name, boolean_varlist[i].name) == 0)
  981.     {
  982.       /* A variable is TRUE if the "value" is "on", "1" or "". */
  983.       if ((!*value) ||
  984.           (stricmp (value, "On") == 0) ||
  985.           (value[0] == '1' && value[1] == '\0'))
  986.         *boolean_varlist[i].value = 1;
  987.       else
  988.         *boolean_varlist[i].value = 0;
  989.       return 0;
  990.     }
  991.     }
  992.  
  993.   /* Not a boolean variable, so check for specials. */
  994.  
  995.   /* Editing mode change? */
  996.   if (stricmp (name, "editing-mode") == 0)
  997.     {
  998.       if (strnicmp (value, "vi", 2) == 0)
  999.     {
  1000. #if defined (VI_MODE)
  1001.       _rl_keymap = vi_insertion_keymap;
  1002.       rl_editing_mode = vi_mode;
  1003. #else
  1004. #if defined (NOTDEF)
  1005.       ding ();
  1006. #endif /* NOTDEF */
  1007. #endif /* VI_MODE */
  1008.     }
  1009.       else if (strnicmp (value, "emacs", 5) == 0)
  1010.     {
  1011.       _rl_keymap = emacs_standard_keymap;
  1012.       rl_editing_mode = emacs_mode;
  1013.     }
  1014.     }
  1015.  
  1016.   /* Comment string change? */
  1017.   else if (stricmp (name, "comment-begin") == 0)
  1018.     {
  1019. #if defined (VI_MODE)
  1020.       extern char *rl_vi_comment_begin;
  1021.  
  1022.       if (*value)
  1023.     {
  1024.       if (rl_vi_comment_begin)
  1025.         free (rl_vi_comment_begin);
  1026.  
  1027.       rl_vi_comment_begin = savestring (value);
  1028.     }
  1029. #endif /* VI_MODE */
  1030.     }
  1031.   else if (stricmp (name, "completion-query-items") == 0)
  1032.     {
  1033.       int nval = 100;
  1034.       if (*value)
  1035.     {
  1036.       nval = atoi (value);
  1037.       if (nval < 0)
  1038.         nval = 0;
  1039.     }
  1040.       rl_completion_query_items = nval;
  1041.     }
  1042.   return 0;
  1043. }
  1044.  
  1045. /* Return the character which matches NAME.
  1046.    For example, `Space' returns ' '. */
  1047.  
  1048. typedef struct {
  1049.   char *name;
  1050.   int value;
  1051. } assoc_list;
  1052.  
  1053. static assoc_list name_key_alist[] = {
  1054.   { "DEL", 0x7f },
  1055.   { "ESC", '\033' },
  1056.   { "Escape", '\033' },
  1057.   { "LFD", '\n' },
  1058.   { "Newline", '\n' },
  1059.   { "RET", '\r' },
  1060.   { "Return", '\r' },
  1061.   { "Rubout", 0x7f },
  1062.   { "SPC", ' ' },
  1063.   { "Space", ' ' },
  1064.   { "Tab", 0x09 },
  1065.   { (char *)0x0, 0 }
  1066. };
  1067.  
  1068. static int
  1069. glean_key_from_name (name)
  1070.      char *name;
  1071. {
  1072.   register int i;
  1073.  
  1074.   for (i = 0; name_key_alist[i].name; i++)
  1075.     if (stricmp (name, name_key_alist[i].name) == 0)
  1076.       return (name_key_alist[i].value);
  1077.  
  1078.   return (*(unsigned char *)name);    /* XXX was return (*name) */
  1079. }
  1080.  
  1081. /* Auxiliary functions to manage keymaps. */
  1082. static struct {
  1083.   char *name;
  1084.   Keymap map;
  1085. } keymap_names[] = {
  1086.   { "emacs", emacs_standard_keymap },
  1087.   { "emacs-standard", emacs_standard_keymap },
  1088.   { "emacs-meta", emacs_meta_keymap },
  1089.   { "emacs-ctlx", emacs_ctlx_keymap },
  1090. #if defined (VI_MODE)
  1091.   { "vi", vi_movement_keymap },
  1092.   { "vi-move", vi_movement_keymap },
  1093.   { "vi-command", vi_movement_keymap },
  1094.   { "vi-insert", vi_insertion_keymap },
  1095. #endif /* VI_MODE */
  1096.   { (char *)0x0, (Keymap)0x0 }
  1097. };
  1098.  
  1099. Keymap
  1100. rl_get_keymap_by_name (name)
  1101.      char *name;
  1102. {
  1103.   register int i;
  1104.  
  1105.   for (i = 0; keymap_names[i].name; i++)
  1106.     if (strcmp (name, keymap_names[i].name) == 0)
  1107.       return (keymap_names[i].map);
  1108.   return ((Keymap) NULL);
  1109. }
  1110.  
  1111. void
  1112. rl_set_keymap (map)
  1113.      Keymap map;
  1114. {
  1115.   if (map)
  1116.     _rl_keymap = map;
  1117. }
  1118.  
  1119. Keymap
  1120. rl_get_keymap ()
  1121. {
  1122.   return (_rl_keymap);
  1123. }
  1124.  
  1125. void
  1126. rl_set_keymap_from_edit_mode ()
  1127. {
  1128.   if (rl_editing_mode == emacs_mode)
  1129.     _rl_keymap = emacs_standard_keymap;
  1130. #if defined (VI_MODE)
  1131.   else if (rl_editing_mode == vi_mode)
  1132.     _rl_keymap = vi_insertion_keymap;
  1133. #endif /* VI_MODE */
  1134. }
  1135.  
  1136. /* **************************************************************** */
  1137. /*                                    */
  1138. /*          Key Binding and Function Information            */
  1139. /*                                    */
  1140. /* **************************************************************** */
  1141.  
  1142. /* Each of the following functions produces information about the
  1143.    state of keybindings and functions known to Readline.  The info
  1144.    is always printed to rl_outstream, and in such a way that it can
  1145.    be read back in (i.e., passed to rl_parse_and_bind (). */
  1146.  
  1147. /* Print the names of functions known to Readline. */
  1148. void
  1149. rl_list_funmap_names (ignore)
  1150.      int ignore;
  1151. {
  1152.   register int i;
  1153.   char **funmap_names;
  1154.  
  1155.   funmap_names = rl_funmap_names ();
  1156.  
  1157.   if (!funmap_names)
  1158.     return;
  1159.  
  1160.   for (i = 0; funmap_names[i]; i++)
  1161.     fprintf (rl_outstream, "%s\n", funmap_names[i]);
  1162.  
  1163.   free (funmap_names);
  1164. }
  1165.  
  1166. /* Return a NULL terminated array of strings which represent the key
  1167.    sequences that are used to invoke FUNCTION in MAP. */
  1168. static char **
  1169. invoking_keyseqs_in_map (function, map)
  1170.      Function *function;
  1171.      Keymap map;
  1172. {
  1173.   register int key;
  1174.   char **result;
  1175.   int result_index, result_size;
  1176.  
  1177.   result = (char **)NULL;
  1178.   result_index = result_size = 0;
  1179.  
  1180.   for (key = 0; key < 128; key++)
  1181.     {
  1182.       switch (map[key].type)
  1183.     {
  1184.     case ISMACR:
  1185.       /* Macros match, if, and only if, the pointers are identical.
  1186.          Thus, they are treated exactly like functions in here. */
  1187.     case ISFUNC:
  1188.       /* If the function in the keymap is the one we are looking for,
  1189.          then add the current KEY to the list of invoking keys. */
  1190.       if (map[key].function == function)
  1191.         {
  1192.           char *keyname = (char *)xmalloc (5);
  1193.  
  1194.           if (CTRL_P (key))
  1195.         sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
  1196.           else if (key == RUBOUT)
  1197.         sprintf (keyname, "\\C-?");
  1198.           else if (key == '\\' || key == '"')
  1199.         {
  1200.           keyname[0] = '\\';
  1201.           keyname[1] = (char) key;
  1202.           keyname[2] = '\0';
  1203.         }
  1204.           else
  1205.         {
  1206.           keyname[0] = (char) key;
  1207.           keyname[1] = '\0';
  1208.         }
  1209.  
  1210.           if (result_index + 2 > result_size)
  1211.         result = (char **) xrealloc
  1212.           (result, (result_size += 10) * sizeof (char *));
  1213.  
  1214.           result[result_index++] = keyname;
  1215.           result[result_index] = (char *)NULL;
  1216.         }
  1217.       break;
  1218.  
  1219.     case ISKMAP:
  1220.       {
  1221.         char **seqs = (char **)NULL;
  1222.  
  1223.         /* Find the list of keyseqs in this map which have FUNCTION as
  1224.            their target.  Add the key sequences found to RESULT. */
  1225.         if (map[key].function)
  1226.           seqs =
  1227. #if defined (CRAY)
  1228.         invoking_keyseqs_in_map (function, (Keymap)((int)map[key].function));
  1229. #else
  1230.         invoking_keyseqs_in_map (function, (Keymap)map[key].function);
  1231. #endif
  1232.  
  1233.         if (seqs)
  1234.           {
  1235.         register int i;
  1236.  
  1237.         for (i = 0; seqs[i]; i++)
  1238.           {
  1239.             char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
  1240.  
  1241.             if (key == ESC)
  1242.               sprintf (keyname, "\\e");
  1243.             else if (CTRL_P (key))
  1244.               sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
  1245.             else if (key == RUBOUT)
  1246.               sprintf (keyname, "\\C-?");
  1247.             else if (key == '\\' || key == '"')
  1248.               {
  1249.             keyname[0] = '\\';
  1250.             keyname[1] = (char) key;
  1251.             keyname[2] = '\0';
  1252.               }
  1253.             else
  1254.               {
  1255.             keyname[0] = (char) key;
  1256.             keyname[1] = '\0';
  1257.               }
  1258.  
  1259.             strcat (keyname, seqs[i]);
  1260.             free (seqs[i]);
  1261.  
  1262.             if (result_index + 2 > result_size)
  1263.               result = (char **) xrealloc
  1264.             (result, (result_size += 10) * sizeof (char *));
  1265.  
  1266.             result[result_index++] = keyname;
  1267.             result[result_index] = (char *)NULL;
  1268.           }
  1269.  
  1270.         free (seqs);
  1271.           }
  1272.       }
  1273.       break;
  1274.     }
  1275.     }
  1276.   return (result);
  1277. }
  1278.  
  1279. /* Return a NULL terminated array of strings which represent the key
  1280.    sequences that can be used to invoke FUNCTION using the current keymap. */
  1281. char **
  1282. rl_invoking_keyseqs (function)
  1283.      Function *function;
  1284. {
  1285.   return (invoking_keyseqs_in_map (function, _rl_keymap));
  1286. }
  1287.  
  1288. /* Print all of the current functions and their bindings to
  1289.    rl_outstream.  If an explicit argument is given, then print
  1290.    the output in such a way that it can be read back in. */
  1291. int
  1292. rl_dump_functions (count)
  1293.      int count;
  1294. {
  1295.   void rl_function_dumper ();
  1296.  
  1297.   rl_function_dumper (rl_explicit_arg);
  1298.   rl_on_new_line ();
  1299.   return (0);
  1300. }
  1301.  
  1302. /* Print all of the functions and their bindings to rl_outstream.  If
  1303.    PRINT_READABLY is non-zero, then print the output in such a way
  1304.    that it can be read back in. */
  1305. void
  1306. rl_function_dumper (print_readably)
  1307.      int print_readably;
  1308. {
  1309.   register int i;
  1310.   char **names;
  1311.   char *name;
  1312.  
  1313.   names = rl_funmap_names ();
  1314.  
  1315.   fprintf (rl_outstream, "\n");
  1316.  
  1317.   for (i = 0; (name = names[i]) != NULL; i++)
  1318.     {
  1319.       Function *function;
  1320.       char **invokers;
  1321.  
  1322.       function = rl_named_function (name);
  1323.       invokers = invoking_keyseqs_in_map (function, _rl_keymap);
  1324.  
  1325.       if (print_readably)
  1326.     {
  1327.       if (!invokers)
  1328.         fprintf (rl_outstream, "# %s (not bound)\n", name);
  1329.       else
  1330.         {
  1331.           register int j;
  1332.  
  1333.           for (j = 0; invokers[j]; j++)
  1334.         {
  1335.           fprintf (rl_outstream, "\"%s\": %s\n",
  1336.                invokers[j], name);
  1337.           free (invokers[j]);
  1338.         }
  1339.  
  1340.           free (invokers);
  1341.         }
  1342.     }
  1343.       else
  1344.     {
  1345.       if (!invokers)
  1346.         fprintf (rl_outstream, "%s is not bound to any keys\n",
  1347.              name);
  1348.       else
  1349.         {
  1350.           register int j;
  1351.  
  1352.           fprintf (rl_outstream, "%s can be found on ", name);
  1353.  
  1354.           for (j = 0; invokers[j] && j < 5; j++)
  1355.         {
  1356.           fprintf (rl_outstream, "\"%s\"%s", invokers[j],
  1357.                invokers[j + 1] ? ", " : ".\n");
  1358.         }
  1359.  
  1360.           if (j == 5 && invokers[j])
  1361.         fprintf (rl_outstream, "...\n");
  1362.  
  1363.           for (j = 0; invokers[j]; j++)
  1364.         free (invokers[j]);
  1365.  
  1366.           free (invokers);
  1367.         }
  1368.     }
  1369.     }
  1370. }
  1371.  
  1372.  
  1373. /* **************************************************************** */
  1374. /*                                    */
  1375. /*            String Utility Functions            */
  1376. /*                                    */
  1377. /* **************************************************************** */
  1378.  
  1379. #ifndef HAVE_STRINDEX
  1380. static char *strindex ();
  1381. #endif
  1382.  
  1383. /* Return non-zero if any members of ARRAY are a substring in STRING. */
  1384. static int
  1385. substring_member_of_array (string, array)
  1386.      char *string, **array;
  1387. {
  1388.   while (*array)
  1389.     {
  1390.       if (strindex (string, *array))
  1391.     return (1);
  1392.       array++;
  1393.     }
  1394.   return (0);
  1395. }
  1396.  
  1397. /* Whoops, Unix doesn't have strnicmp. */
  1398.  
  1399. #ifndef HAVE_STRNICMP
  1400. /* Compare at most COUNT characters from string1 to string2.  Case
  1401.    doesn't matter. */
  1402. static int
  1403. strnicmp (string1, string2, count)
  1404.      char *string1, *string2;
  1405.      int count;
  1406. {
  1407.   register char ch1, ch2;
  1408.  
  1409.   while (count)
  1410.     {
  1411.       ch1 = *string1++;
  1412.       ch2 = *string2++;
  1413.       if (to_upper(ch1) == to_upper(ch2))
  1414.     count--;
  1415.       else break;
  1416.     }
  1417.   return (count);
  1418. }
  1419. #endif
  1420.  
  1421. #ifndef HAVE_STRICMP
  1422. /* strcmp (), but caseless. */
  1423. static int
  1424. stricmp (string1, string2)
  1425.      char *string1, *string2;
  1426. {
  1427.   register char ch1, ch2;
  1428.  
  1429.   while (*string1 && *string2)
  1430.     {
  1431.       ch1 = *string1++;
  1432.       ch2 = *string2++;
  1433.       if (to_upper(ch1) != to_upper(ch2))
  1434.     return (1);
  1435.     }
  1436.   return (*string1 | *string2);
  1437. }
  1438. #endif
  1439.  
  1440. #ifndef HAVE_STRINDEX
  1441. /* Determine if s2 occurs in s1.  If so, return a pointer to the
  1442.    match in s1.  The compare is case insensitive. */
  1443. static char *
  1444. strindex (s1, s2)
  1445.      register char *s1, *s2;
  1446. {
  1447.   register int i, l = strlen (s2);
  1448.   register int len = strlen (s1);
  1449.  
  1450.   for (i = 0; (len - i) >= l; i++)
  1451.     if (strnicmp (&s1[i], s2, l) == 0)
  1452.       return (s1 + i);
  1453.   return ((char *)NULL);
  1454. }
  1455. #endif
  1456.